2016-08-03 4 views
6

मेरे पास डेटा का डेटा और फिट गुणांक का एक डाटाटेबल है। मैं प्रत्येक पंक्ति के लिए फिट मान की गणना करना चाहता हूं।आर डेटाटेबल डॉट उत्पाद मिलान कॉलम नामों (प्रत्येक समूह के लिए)

dt = data.table(a = rep(c("x","y"), each = 5), b = rnorm(10), c = rnorm(10), d = rnorm(10)) 
coefs = data.table(a = c("x","y"), b = c(0, 1), d = c(2,3)) 
dt 
# a   b   c   d 
# 1: x -0.25174915 -0.2130797 -0.67909764 
# 2: x -0.35569766 0.6014930 0.35201386 
# 3: x -0.31600957 0.4398968 -1.15475814 
# 4: x -0.54113762 -2.3497952 0.64503654 
# 5: x 0.11227873 0.0233775 -0.96891456 
# 6: y 1.24077566 -1.2843439 1.98883516 
# 7: y -0.23819626 0.9950835 -0.17279980 
# 8: y 1.49353589 0.3067897 -0.02592004 
# 9: y 0.01033722 -0.5967766 -0.28536224 
#10: y 0.69882444 0.8702424 1.24131062 

coefs # NB no "c" column 
# a b d 
#1: x 0 2 
#2: y 1 3 

डीटी में प्रत्येक a=="x" पंक्ति के लिए, मैं 0*b+2*d चाहते हैं; और डीटी में प्रत्येक a=="y" पंक्ति के लिए, मुझे 1*b+3*d चाहिए।

कॉलम नाम हार्डकोड किए बिना ऐसा करने का कोई डेटाटेबल तरीका है? मुझे कॉलम नामों को एक चर cols = colnames(coefs)[-1] में रखने में खुशी है।

समूह और rbind पर लूप करना आसान है, इसलिए यदि समूह समस्या उत्पन्न कर रहा है, तो कृपया उस भाग को अनदेखा करें।

+0

मेरा समान प्रश्न: http://stackoverflow.com/q/19279075/ इसके लायक होने के लिए, मुझे लगता है कि यह स्वाभाविक है कि कोई व्यक्ति गतिशील रूप से मिलान करने के बारे में चिंतित होगा, और यह इस सवाल को "चलती लक्ष्य" नहीं बनाता है " बिलकुल। – Frank

उत्तर

8

data.tables में शामिल हों:

dt[coefs, res := b * i.b + d * i.d, on = "a"] 
# a   b   c   d  res 
#1: x 0.09901786 -0.362080111 -0.5108862 -1.0217723 
#2: x -0.16128422 0.169655945 0.3199648 0.6399295 
#3: x -0.79648896 -0.502279345 1.3828633 2.7657266 
#4: x -0.26121421 0.480548972 -1.1559392 -2.3118783 
#5: x 0.54085591 -0.601323442 1.3833795 2.7667590 
#6: y 0.83662761 0.607666970 0.6320762 2.7328562 
#7: y -1.92510391 -0.050515610 -0.3176544 -2.8780671 
#8: y 1.65639926 -0.167090105 0.6830158 3.7054466 
#9: y 1.48772354 -0.349713539 -1.2736467 -2.3332166 
#10: y 1.49065993 0.008198885 -0.1923361 0.9136516 

आमतौर पर आप मैट्रिक्स उत्पाद यहाँ का प्रयोग करेंगे, लेकिन इसका मतलब यह है कि आप एक मैट्रिक्स के लिए संबंधित सबसेट मजबूर करने के लिए किया था। इसके परिणामस्वरूप एक प्रतिलिपि बनाई जा रही है और चूंकि डेटाटेबल मुख्य रूप से बड़े डेटा के लिए उपयोग किए जाते हैं, इसलिए आप प्रतियों से बचना चाहते हैं।

cols = colnames(coefs)[-1] 
expr <- parse(text = paste(paste(cols, paste0("i.", cols), sep = "*"), collapse = "+")) 
#expression(b*i.b+d*i.d) 

dt[coefs, res := eval(expr), on = "a"] 

हो सकता है कि किसी और एक बेहतर समाधान का सुझाव कर सकते हैं:

आप गतिशील स्तंभ नाम की जरूरत है, सबसे सरल उपाय है कि मन में आता है वास्तव में एक eval/parse निर्माण है।

dt[, res := as.matrix(.SD) %*% unlist(coefs[a == .BY, .SD, .SDcols = cols]), 
    by = "a", .SDcols = cols] 

बेशक इस प्रतियां बनाता है, जो संभवतः कम कुशल eval समाधान है तो:

यहाँ एक समाधान का उपयोग कर आव्यूह गुणन है।

+0

धन्यवाद। क्या कॉलम नाम को हार्डकोड करना संभव नहीं है? मुझे उन्हें 'cols = colnames (coefs) [- 1]' जैसे चर में डालकर खुशी हुई है और फिर वहां से कैसे जाना है? – jf328

+3

कृपया अपना प्रश्न एक आगे बढ़ने का लक्ष्य न बनाएं। जब आप कोई प्रश्न पूछते हैं तो सभी विनिर्देश प्रदान करें। – Roland

0

मुझे पता चला कि सभी संख्यात्मक प्रकार के कॉलम का डेटाटेबल अंकगणितीय परिचालन (+, -, *, /) कर सकता है, लेकिन कोई नाम मिलान नहीं कर रहा है - बस ऑर्डर मिलान करें।

> coefs 
    a b d 
1: x 0 2 
2: y 1 3 
> coefs[, .(b,d)] * coefs[, .(b,d)] 
    b d 
1: 0 4 
2: 1 9 
> coefs[, .(b,d)] * coefs[, .(d,b)] 
    b d 
1: 0 0 
2: 3 3 

तो एक समाधान यह

> cols = colnames(coefs)[-1] 
> zz = rowSums(coefs[dt[,.(a)], .SD, on = 'a', .SDcols = cols] * dt[, .SD, .SDcols = cols]) 
> dt[, newcol := zz] 
+0

यदि आपको कॉपी नहीं है (जो 'पंक्तिसमूह' डेटा मैट्रिक्स को डेटाटेबल को जोड़कर बनाता है), तो आपको अपने अंतिम सुझाव, यानी मैट्रिक्स गुणा का उपयोग करना चाहिए। – Roland

0

एक अन्य विकल्प के आधार पर (लेकिन धीमी) दृष्टिकोण है:

dt$res <- unsplit(Map(function(x,y){x$b*y$b + x$d*y$d}, split(dt, dt$a=="x"), 
       split(coefs,coefs$a=="x")),dt$a=="x") 

    dt 
    a   b   c   d  res 
1: x 0.47859729 1.3479271 0.5691897 1.1383794 
2: x 0.28491505 -0.3291934 1.8621365 3.7242730 
3: x -1.43894695 1.5555413 0.3685772 0.7371544 
4: x 0.04360066 0.1358920 0.5240700 1.0481400 
5: x -1.39897890 -0.0175886 -0.6876451 -1.3752901 
6: y -0.60952146 1.2331907 -0.3582176 -1.6841742 
7: y 0.31777772 1.4090295 -0.4053615 -0.8983067 
8: y 0.42758431 -0.3746061 2.1208417 6.7901094 
9: y -0.60701063 -0.9232092 1.9386482 5.2089341 
10: y -1.52042316 -0.8871454 -0.9314232 -4.3146927 

यह वही कोड बेस आर में काम करेगा और साथ ही अपने डेटा था अगर पहले से ही data.frames

+0

यह निश्चित रूप से बड़े डेटा के लिए कुशल नहीं है। – Roland

+0

ठीक है, बस इसे करने का एक अलग तरीका दिखाना चाहता था। –

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