2013-02-21 31 views
10

पर कॉलम नाम पास करने के लिए मैं एक ऐसा फ़ंक्शन लिखने में सक्षम होना चाहता हूं जो समूहों द्वारा data.table में प्रतिगमन चलाता है और फिर परिणामों को अच्छी तरह से व्यवस्थित करता है।डेटाटेबल प्रोग्रामेटिक रूप से

require(data.table) 
dtb = data.table(y=1:10, x=10:1, z=sample(1:10), weights=1:10, thedate=1:2) 
models = c("y ~ x", "y ~ z") 

res = lapply(models, function(f) {dtb[,as.list(coef(lm(f, weights=weights, data=.SD))),by=thedate]}) 

#do more stuff with res 

मैं के बाद से #doe more stuff लंबे हो सकता है एक समारोह में यह सब रैप करने के लिए करना चाहते हैं: यहाँ मैं करना चाहते हैं क्या का एक नमूना है। मुझे जिस मुद्दे का सामना करना पड़ता है वह है कि data.table पर चीजों के विभिन्न नामों को कैसे पास किया जाए? उदाहरण के लिए, मैं कॉलम नाम weights कैसे पास करूं? मैं thedate कैसे पास करूं? मैं एक प्रोटोटाइप है कि इस तरह दिखता है कल्पना:

myfun = function(dtb, models, weights, dates) 

मुझे स्पष्ट हो: मेरे कार्य करने के लिए फार्मूले गुजर समस्या नहीं है। यदि weights मैं उपयोग करना चाहता था और तारीख का वर्णन स्तंभ नाम, thedate में जाने जाते थे तो मेरे समारोह बस ऐसा दिखाई दे सकता:

myfun = function(dtb, models) { 
res = lapply(models, function(f) {dtb[,as.list(coef(lm(f, weights=weights, data=.SD))),by=thedate]}) 

#do more stuff with res 
} 

हालांकि स्तंभ thedate करने और weights करने के लिए इसी नाम पहले से अनजान हैं। मैं उन्हें इतनी के रूप में मेरे कार्य करने के लिए पारित करने के लिए करना चाहते हैं:

#this will not work 
myfun = function(dtb, models, w, d) { 
res = lapply(models, function(f) {dtb[,as.list(coef(lm(f, weights=w, data=.SD))),by=d]}) 

#do more stuff with res 
} 

धन्यवाद

उत्तर

5

यहाँ, एक समाधान है कि लंबे समय से प्रारूप में डेटा (जो मेरे लिए अधिक समझ में आता है होने पर निर्भर करता है इस

library(reshape2) 
dtlong <- data.table(melt(dtb, measure.var = c('x','z'))) 


foo <- function(f, d, by, w){ 
    # get the name of the w argument (weights) 
    w.char <- deparse(substitute(w)) 
    # convert `list(a,b)` to `c('a','b')` 
    # obviously, this would have to change depending on how `by` was defined 
    by <- unlist(lapply(as.list(as.list(match.call())[['by']])[-1], as.character)) 
    # create the call substituting the names as required 
    .c <- substitute(as.list(coef(lm(f, data = .SD, weights = w), list(w = as.name(w.char))))) 
    # actually perform the calculations 
    d[,eval(.c), by = by] 
} 

foo(f= y~value, d= dtlong, by = list(variable, thedate), w = weights) 

    variable thedate (Intercept)  value 
1:  x  1 11.000000 -1.00000000 
2:  x  2 11.000000 -1.00000000 
3:  z  1 1.009595 0.89019190 
4:  z  2 7.538462 -0.03846154 
+0

दिलचस्प। धन्यवाद! – Alex

+0

+1 शायद '.BY'' match.call() 'लाइन से बचने के लिए यहां उपयोगी है, सुनिश्चित नहीं है। –

1

तुम सिर्फ (अनाम समारोह कॉल के अंदर) नहीं जोड़ सकते:

f <- as.formula(f) 

... एक के रूप में dtb[,as.list(coef(lm(f, ...) से पहले अलग लाइन? चरित्र तत्व को फ़ॉर्मूला ऑब्जेक्ट में बदलने का यह सामान्य तरीका है।

> res = lapply(models, function(f) {f <- as.formula(f) 
       dtb[,as.list(coef(lm(f, weights=weights, data=.SD))),by=thedate]}) 
> 
> str(res) 
List of 2 
$ :Classes ‘data.table’ and 'data.frame': 2 obs. of 3 variables: 
    ..$ thedate : int [1:2] 1 2 
    ..$ (Intercept): num [1:2] 11 11 
    ..$ x   : num [1:2] -1 -1 
    ..- attr(*, ".internal.selfref")=<externalptr> 
$ :Classes ‘data.table’ and 'data.frame': 2 obs. of 3 variables: 
    ..$ thedate : int [1:2] 1 2 
    ..$ (Intercept): num [1:2] 6.27 11.7 
    ..$ z   : num [1:2] 0.0633 -0.7995 
    ..- attr(*, ".internal.selfref")=<externalptr> 

आप, घटकों के नाम से सूत्रों के चरित्र संस्करणों का निर्माण सिर्फ paste या paste0 का उपयोग करें और मॉडल चरित्र वेक्टर को पारित करने के लिए की जरूरत है। टेस्टेबल उदाहरणों की प्राप्ति के साथ प्रदान किया गया परीक्षण कोड।

+0

सूत्र nto है कैस में मुद्दा, 'एलएम' तारों को ठीक करता है। मुद्दा 'वजन' और 'thedate' – Alex

+0

है, मुझे लगता है कि आपने मेरे प्रश्न को गलत समझा होगा। मैं उस कोड को एक समारोह में रखना चाहता हूं – Alex

+0

मैंने जो कुछ उदाहरण के साथ समझदार था प्रदान किया गया। कृपया अपना उदाहरण संपादित करें। –

3

एक संभव समाधान:

fun = function(dtb, models, w_col_name, date_name) { 
    res = lapply(models, function(f) {dtb[,as.list(coef(lm(f, weights=eval(parse(text=w_col_name)), data=.SD))),by=eval(parse(text=paste0("list(",date_name,")")))]}) 

} 
+1

+1 सोचें कि आप इस मामले में 'eval (parse()) के बजाय' get() 'का उपयोग कर सकते हैं, सुनिश्चित नहीं है। –

संबंधित मुद्दे