R data.table गणना में पिछली पंक्ति के मान का उपयोग करें


81

मैं एक कॉलम के वर्तमान मूल्य और दूसरे के पिछले भाग से गणना की गई डेटाटेबल में एक नया कॉलम बनाना चाहता हूं। क्या पिछली पंक्तियों तक पहुंच संभव है?

जैसे:

> DT <- data.table(A=1:5, B=1:5*10, C=1:5*100)
> DT
   A  B   C
1: 1 10 100
2: 2 20 200
3: 3 30 300
4: 4 40 400
5: 5 50 500
> DT[, D := C + BPreviousRow] # What is the correct code here?

सही उत्तर होना चाहिए

> DT
   A  B   C   D
1: 1 10 100  NA
2: 2 20 200 210
3: 3 30 300 320
4: 4 40 400 430
5: 5 50 500 540

मैं आमतौर पर मेरी data.tables करने के लिए एक कुंजी सेट:DT <- data.table(A=..., key = "A")
PatrickT

जवाबों:


103

V1.9.6shift() में लागू होने के साथ , यह काफी सीधा है।

DT[ , D := C + shift(B, 1L, type="lag")]
# or equivalently, in this case,
DT[ , D := C + shift(B)]

से समाचार :

  1. नया फंक्शन वेक्टर , लिस्ट , डेटा.फ्रेम या data.tables केshift() तेजी lead/lagसे लागू होता है । यह एक तर्क लेता है जो या तो "अंतराल" (डिफ़ॉल्ट) या "लीड" हो सकता है । यह साथ या साथ बहुत सुविधाजनक उपयोग को सक्षम करता है । उदाहरण के लिए :। कृपया अधिक जानकारी के लिए एक नज़र है ।type:=set()DT[, (cols) := shift(.SD, 1L), by=id]?shift

पिछले उत्तरों के लिए इतिहास देखें।


क्या यह .Nवर्तमान पंक्ति संख्या या कुछ और है? यहाँ पूछने के लिए क्षमा करें, लेकिन मैं इसे मदद फ़ाइलों में खोजने के लिए प्रतीत नहीं कर सकता ...
SlowLearner

7
@ स्लोनलर: आपको .Iउपयोगी भी मिल सकता है , जो कर्ण समूह में पंक्तियों के लिए पंक्ति सूचकांकों को रखता है।
स्टीव लियानोग्लू

7
1 :(। N-1) के बजाय seq_len (.N - 1) का उपयोग करें। यह 1: 0 से जुड़ी समस्याओं से बचा जाता है।
19

1
.SDउदाहरण के लिए +1 - मैं एक का उपयोग करने lapplyऔर फंकी परिणाम प्राप्त करने की कोशिश कर रहा था । यह बहुत सरल है।
माइकलचिरिको

मुझे इस सभी नई जानकारी के साथ एक अद्यतन पीडीएफ कहां मिल सकती है? आधिकारिक 1.9.4 विगनेट्स और वेबमिनार इसमें शामिल नहीं हैं। और Rmd 1.9.5 विगनेट सहज नहीं हैं और इसमें शामिल नहीं हैं।
स्कैन


22

कई लोगों ने विशिष्ट प्रश्न का उत्तर दिया है। एक सामान्य उद्देश्य फ़ंक्शन के लिए नीचे दिए गए कोड को देखें जो मैं इस तरह की स्थितियों में उपयोग करता हूं जो सहायक हो सकते हैं। केवल पूर्व पंक्ति प्राप्त करने के बजाय, आप "भूतकाल" या "भविष्य" में जितनी चाहें उतनी पंक्तियाँ ले सकते हैं।

rowShift <- function(x, shiftLen = 1L) {
  r <- (1L + shiftLen):(length(x) + shiftLen)
  r[r<1] <- NA
  return(x[r])
}

# Create column D by adding column C and the value from the previous row of column B:
DT[, D := C + rowShift(B,-1)]

# Get the Old Faithul eruption length from two events ago, and three events in the future:
as.data.table(faithful)[1:5,list(eruptLengthCurrent=eruptions,
                                 eruptLengthTwoPrior=rowShift(eruptions,-2), 
                                 eruptLengthThreeFuture=rowShift(eruptions,3))]
##   eruptLengthCurrent eruptLengthTwoPrior eruptLengthThreeFuture
##1:              3.600                  NA                  2.283
##2:              1.800                  NA                  4.533
##3:              3.333               3.600                     NA
##4:              2.283               1.800                     NA
##5:              4.533               3.333                     NA

यह एक शानदार जवाब है, मुझे गुस्सा आ रहा है कि मैं पहले ही दूसरे जवाबों को उखाड़ फेंक चुका हूं क्योंकि यह एक अधिक सामान्य जवाब है। वास्तव में, मैं इसे अपने जीनोरमा पैकेज में उपयोग करने जा रहा हूं (यदि आपको कोई आपत्ति नहीं है)।
जीनोरमा 19

ज़रूर जाना, इसके लिए। मैं कुछ खाली समय पाने और data.tableपैकेज के लिए एक पुल अनुरोध के रूप में प्रस्तुत करने की उम्मीद कर रहा था , लेकिन अफसोस ...
dnlbrky

एक समान फ़ंक्शन को संस्करण 1.9.5 के रूप shiftमें जोड़ा गया है data.table। @Arun से अद्यतन उत्तर देखें ।
dnlbrky

12

ऊपर @Steve लियानोग्लू की टिप्पणी के आधार पर, बस क्यों नहीं:

DT[, D:= C + c(NA, B[.I - 1]) ]
#    A  B   C   D
# 1: 1 10 100  NA
# 2: 2 20 200 210
# 3: 3 30 300 320
# 4: 4 40 400 430
# 5: 5 50 500 540

और उपयोग करने से बचें seq_lenया headया किसी अन्य कार्य करते हैं।


2
अच्छा - हालाँकि यह काम नहीं करेगा यदि आप एक समूह के भीतर पिछले खोजना चाहते थे।
मैथ्यू

1
@ मैथ्यू आप सही कह रहे हैं। मैं जगह लेंगे समूह द्वारा subsetting तो .Iसाथseq_len(.N)
गैरी Weissman

9

अरुण के समाधान के बाद, इसी तरह के परिणाम को संदर्भित किए बिना प्राप्त किया जा सकता है .N

> DT[, D := C + c(NA, head(B, -1))][]
   A  B   C   D
1: 1 10 100  NA
2: 2 20 200 210
3: 3 30 300 320
4: 4 40 400 430
5: 5 50 500 540

क्या एक विधि से दूसरे तरीके को पसंद करने का कोई कारण है? या यह केवल एक सौंदर्य अंतर है?
कोरोन

मुझे लगता है कि इस परिदृश्य में (यानी जहां .Nआसानी से उपलब्ध है) यह ज्यादातर सौंदर्य पसंद है। मैं किसी भी महत्वपूर्ण अंतर से अवगत नहीं हूं।
Ryogi

1

मैंने एक पैडिंग तर्क जोड़ा और कुछ नामों को बदल दिया और इसे बुलाया shifthttps://github.com/geneorama/geneorama/blob/master/R/shift.R


1
नोट के लिए बहुत बहुत धन्यवाद। मैं इसके लिए तलाश कर रहा हूँ, और सबसे अधिक संभावना है कि इसका उपयोग करें और मेरे जीनोरमा संस्करण को हटा दें।
जीनोरमा 20

1

यहाँ मेरा सहज समाधान है:

#create data frame
df <- data.frame(A=1:5, B=seq(10,50,10), C=seq(100,500, 100))`
#subtract the shift from num rows
shift  <- 1 #in this case the shift is 1
invshift <- nrow(df) - shift
#Now create the new column
df$D <- c(NA, head(df$B, invshift)+tail(df$C, invshift))`

यहाँ invshift, पंक्तियों की संख्या 1 घटाती है, 4. nrow(df)आपको डेटा फ्रेम में या वेक्टर में पंक्तियों की संख्या प्रदान करती है। इसी तरह, यदि आप अभी भी पहले के मूल्यों को लेना चाहते हैं, तो nrow 2, 3, ... आदि से घटाएं, और शुरुआत में NA के अनुसार भी डालें।


-2

यह एक लूप में किया जा सकता है।

# Create the column D
DT$D <- 0
# for every row in DT
for (i in 1:length(DT$A)) {
  if(i==1) {
    #using NA at first line
    DT[i,4] <- NA
  } else {
    #D = C + BPreviousRow
    DT[i,4] <- DT[i,3] + DT[(i-1), 2]   
  }
}

का उपयोग करके, आप इस नए कॉलम की पंक्ति के पिछले मूल्य का भी उपयोग कर सकते हैं DT[(i-1), 4]

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