समूह द्वारा: data.table में = का उपयोग करके कई कॉलम असाइन करें


130

कई कॉलमों का उपयोग करने का सबसे अच्छा तरीका क्या है data.table? उदाहरण के लिए:

f <- function(x) {c("hi", "hello")}
x <- data.table(id = 1:10)

मैं ऐसा कुछ करना चाहूंगा (बेशक यह वाक्य रचना गलत है):

x[ , (col1, col2) := f(), by = "id"]

और इसका विस्तार करने के लिए, मेरे पास एक चर (कह col_names) में संग्रहीत नामों के साथ कई कॉलम हो सकते हैं और मैं करना चाहूंगा:

x[ , col_names := another_f(), by = "id", with = FALSE]

ऐसा कुछ करने का सही तरीका क्या है?


1
ऐसा लगता है कि यह उत्तर दिया गया है: stackoverflow.com/questions/11308754/…
एलेक्स

एलेक्स, यह जवाब करीब है, लेकिन यह by@Christoph_J के साथ संयोजन के रूप में काम करने के लिए सही नहीं लगता है । आपके प्रश्न के लिंक को FR # 2120 में जोड़ा गया है: LHS for: = "के लिए = FALSE के साथ ड्रॉप की आवश्यकता है, इसलिए इसे फिर से लिखना न भूलें।
मैट डाउल

स्पष्ट होने के लिए, f()एक फ़ंक्शन है जो आपके प्रत्येक कॉलम के लिए एक से अधिक मान लौटाता है।
एसएमसीआई

जवाबों:


161

यह अब R-फोर्ज पर v1.8.3 में काम करता है। इसे उजागर करने के लिए धन्यवाद!

x <- data.table(a = 1:3, b = 1:6) 
f <- function(x) {list("hi", "hello")} 
x[ , c("col1", "col2") := f(), by = a][]
#    a b col1  col2
# 1: 1 1   hi hello
# 2: 2 2   hi hello
# 3: 3 3   hi hello
# 4: 1 4   hi hello
# 5: 2 5   hi hello
# 6: 3 6   hi hello

x[ , c("mean", "sum") := list(mean(b), sum(b)), by = a][]
#    a b col1  col2 mean sum
# 1: 1 1   hi hello  2.5   5
# 2: 2 2   hi hello  3.5   7
# 3: 3 3   hi hello  4.5   9
# 4: 1 4   hi hello  2.5   5
# 5: 2 5   hi hello  3.5   7
# 6: 3 6   hi hello  4.5   9 

mynames = c("Name1", "Longer%")
x[ , (mynames) := list(mean(b) * 4, sum(b) * 3), by = a]
#     a b col1  col2 mean sum Name1 Longer%
# 1: 1 1   hi hello  2.5   5    10      15
# 2: 2 2   hi hello  3.5   7    14      21
# 3: 3 3   hi hello  4.5   9    18      27
# 4: 1 4   hi hello  2.5   5    10      15
# 5: 2 5   hi hello  3.5   7    14      21
# 6: 3 6   hi hello  4.5   9    18      27


x[ , get("mynames") := list(mean(b) * 4, sum(b) * 3), by = a][]  # same
#    a b col1  col2 mean sum Name1 Longer%
# 1: 1 1   hi hello  2.5   5    10      15
# 2: 2 2   hi hello  3.5   7    14      21
# 3: 3 3   hi hello  4.5   9    18      27
# 4: 1 4   hi hello  2.5   5    10      15
# 5: 2 5   hi hello  3.5   7    14      21
# 6: 3 6   hi hello  4.5   9    18      27

x[ , eval(mynames) := list(mean(b) * 4, sum(b) * 3), by = a][]   # same
#    a b col1  col2 mean sum Name1 Longer%
# 1: 1 1   hi hello  2.5   5    10      15
# 2: 2 2   hi hello  3.5   7    14      21
# 3: 3 3   hi hello  4.5   9    18      27
# 4: 1 4   hi hello  2.5   5    10      15
# 5: 2 5   hi hello  3.5   7    14      21
# 6: 3 6   hi hello  4.5   9    18      27

withतर्क का उपयोग करते हुए पुराना संस्करण (हम संभव होने पर इस तर्क को हतोत्साहित करते हैं):

x[ , mynames := list(mean(b) * 4, sum(b) * 3), by = a, with = FALSE][] # same
#    a b col1  col2 mean sum Name1 Longer%
# 1: 1 1   hi hello  2.5   5    10      15
# 2: 2 2   hi hello  3.5   7    14      21
# 3: 3 3   hi hello  4.5   9    18      27
# 4: 1 4   hi hello  2.5   5    10      15
# 5: 2 5   hi hello  3.5   7    14      21
# 6: 3 6   hi hello  4.5   9    18      27

इस उत्तर और उदाहरण के लिए धन्यवाद। प्रत्येक आउटपुट के लिए दो कॉलम प्राप्त करने के लिए मुझे निम्न पंक्ति को कैसे संशोधित करना चाहिए, दो पंक्तियों के साथ एक कॉलम के बजाय मंद आउटपुट से? data.table(objectName=ls())[,c("rows","cols"):=dim(get(objectName)),by=objectName](मैं data.table1.8.11 का उपयोग कर रहा हूं )
dnlbrky

@dnlbrky dimएक वेक्टर लौटाता है जिससे टाइप करने के लिए listइसे घुमाना चाहिए; उदा [,c("rows","cols"):=as.list(dim(get(objectName))),by=objectNa‌​me]। परेशानी यह है कि as.listकॉल ओवरहेड है और छोटे वेक्टर को भी कॉपी करता है। यदि दक्षता एक समस्या है क्योंकि समूहों की संख्या बढ़ती है तो कृपया हमें बताएं।
मैट डोले

1
हे मैट। आपके दूसरे कोड ब्लॉक में पहला उदाहरण (यानी x[,mynames:=list(mean(b)*4,sum(b)*3),by=a,with=FALSE][]) अब एक चेतावनी फेंकता है, इसलिए शायद इसे हटा दें? संबंधित नोट पर, क्या किसी ने सुझाव दिया है कि options(datatable.WhenJisSymbolThenCallingScope=TRUE), एक असाइनमेंट जैसा x[,mynames:=list(mean(b)*4,sum(b)*3),by=a]वास्तव में काम करना चाहिए? ऐसा लगता है कि अन्य परिवर्तनों के अनुरूप होगा, हालांकि मुझे लगता है कि यह बहुत अधिक मौजूदा उपयोगकर्ता कोड (?) को तोड़ सकता है।
जोश ओ'ब्रायन

1
@PanFrancisco बिना by=aयह काम करेगा, लेकिन एक अलग उत्तर लौटाएं। mean(a)और sum(a)समुच्चय प्रत्येक समूह जब भीतर पुनर्नवीनीकरण किया जा रहा है by=a। बिना by=aयह सिर्फ लाठी meanऔर sumप्रत्येक कोशिका में संपूर्ण स्तंभ (यानी अलग नंबरों) के लिए।
मैट डॉवले

1
@MattDowle क्या होगा यदि मेरा फ़ंक्शन पहले से ही नाम सूची में लौटता है, क्या वैसे भी मैं फिर से नाम के बिना कॉलम को dt में जोड़ सकता हूं? उदाहरण के लिए f <- function (x) {list ("c" = "hi", "d" = "hello")} x [, f (), by = a] [] नाम वाले कॉल के साथ परिणाम प्रिंट करेगा। मुझे पता नहीं है कि परिणाम को डीटीटी में कैसे जोड़ा जाए।
ज्वेल

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.