2016-03-03 10 views
7

मेरे पास 3 कॉलम: आईडी, समय और स्थिति के साथ एक डेटा.table है। प्रत्येक आईडी के लिए, मैं अधिकतम समय के साथ रिकॉर्ड खोजना चाहता हूं - फिर यदि उस रिकॉर्ड के लिए, स्थिति सत्य है, तो मैं समय> 7 (उदाहरण के लिए) गलत होने पर इसे गलत पर सेट करना चाहता हूं। मैं इसे निम्नलिखित तरीके से कर रहा हूं।डेटा.table अद्यतन स्थिति के आधार पर समूह में अंतिम तत्व

x <- data.table(id=c(1,1,2,2),time=c(5,6,7,8),status=c(FALSE,TRUE,FALSE,TRUE)) 
setkey(x,id,time) 
y <- x[,.SD[.N],by=id] 
x[y,status:=status & time > 7] 

मेरे पास बहुत सारे डेटा हैं जिनके साथ मैं काम कर रहा हूं और इस ऑपरेशन को तेज करना चाहता हूं। किसी भी सुझाव की सराहना की जाएगी!

+0

'' id' भीतर time' अद्वितीय है (इसलिए एक "अधिक से अधिक समय के साथ रिकॉर्ड" है) ? – Frank

+0

व्यक्तिगत रूप से, मैं आपके दृष्टिकोण को उत्तर से बेहतर पसंद करता हूं। मैं इसे 'y = x [, .SD [.N,। (समय, स्थिति)] में बदल सकता हूं, = id] [time> 7 और स्थिति]; एक्स [वाई, स्थिति: = गलत] ', हालांकि। ('। (समय, स्थिति) 'चीज केवल उपयोगी है यदि आपके पास अन्य वर्र्स हैं जो इस शर्त के लिए आवश्यक नहीं हैं।) – Frank

+1

हां, समय आईडी के भीतर अद्वितीय है, इसलिए अधिकतम समय के साथ एक रिकॉर्ड होगा। तुलना के लिए – user2506086

उत्तर

7

एक data.table दृष्टिकोण

x[ x[order(time), .I[.N], by=id]$V1 , status := ifelse(time > 7, FALSE, TRUE)] 

> x 
# id time status 
#1: 1 5 FALSE 
#2: 1 6 TRUE 
#3: 2 7 FALSE 
#4: 2 8 FALSE 

रूप x[order(time), .I[.N], by=id]$V1 हमें प्रत्येक समूह (id)

के लिए अधिकतम time की पंक्ति सूचकांक देता है और, @ Floo0 के जवाब से उधार हम

इसे थोड़ा सा को आसान बनाने में कर सकते हैं
x[ x[order(time), .I[.N], by=id]$V1 , status := status * time <= 7] 

गति तुलना

विभिन्न उत्तरों की एक गति परीक्षण (और डेटा पर कुंजी रखने)

set.seed(123) 
x <- data.table(id=c(rep(seq(1:10000), each=10)), 
       time=c(rep(seq(1:10000), 10)), 
       status=c(sample(c(TRUE, FALSE), 10000*10, replace=T))) 
setkey(x,id,time) 
x1 <- copy(x); x2 <- copy(x); x3 <- copy(x); x4 <- copy(x); x5 <- copy(x); x6 <- copy(x) 

library(microbenchmark) 

microbenchmark(

    Symbolix = {x1[ x1[order(time), .I[.N], by=id]$V1 , status := status * time < 7 ] }, 

    Floo0_1 = {x2[,status := c(.SD[-.N, status], .SD[.N, status * time > 7]), by=id]}, 

    Floo0_2 = {x3[x3[,.N, by=id][,cumsum(N)], status := status * time > 7]}, 

    Original = { 
       y <- x4[,.SD[.N],by=id] 
       x4[y,status:=status & time > 7] 
       }, 

    Frank = { 
      y <- x5[, .SD[.N, .(time, status)], by=id][time > 7 & status] 
      x5[y, status := FALSE] 
      }, 

    thelatemail = {x6[ x6[,.I==.I[which.max(time)], by=id]$V1 & time > 7, status := FALSE]} 
) 

Unit: milliseconds 
     expr   min   lq  mean  median   uq   max neval cld 
    Symbolix 5.419768 5.857477 6.514111 6.222118 6.936000 11.284580 100 a 
    Floo0_1 4550.314775 4710.679867 4787.086279 4776.794072 4850.334011 5097.136148 100 c 
    Floo0_2 1.653419 1.792378 1.945203 1.881609 2.014325 4.096006 100 a 
    Original 10.052947 10.986294 12.541595 11.431182 12.391287 89.494783 100 a 
     Frank 4609.115061 4697.687642 4743.886186 4735.086113 4785.212543 4932.270602 100 b 
thelatemail 10.300864 11.594972 12.421889 12.315852 12.984146 17.630736 100 a 
+2

धन्यवाद, लेकिन मुझे लगता है कि इसे दो सुधारों की आवश्यकता है: 4x3 डेटा.table पर तुलना करना बहुत उबाऊ है। वास्तव में गति की तुलना करने के लिए कृपया 1mio x 3 तालिका या तो जाएं। दूसरा: आपने डेटा-टेबल की कुंजी नहीं बनाई ... क्यों? मूल प्रश्न में कुंजी थी। अधिकांश समाधान 'by'' का उपयोग करते हैं, इससे बड़ा अंतर हो सकता है। – Rentrop

+0

@ फ़्लू 0 - 1: अच्छा बिंदु, मैं थोड़ा सा परीक्षण चलाऊंगा।2: मैंने मूल 'सेटकी' को समाधान का हिस्सा बनने के लिए लिया, सवाल नहीं। लेकिन, मैं मानता हूं कि यह देखने के लिए अच्छा होगा कि क्या होता है यदि सभी समाधानों पर कुंजी सेट की जाती है। – SymbolixAU

+0

मुझे यह जानने में दिलचस्पी होगी कि इसे नीचे वोट क्यों मिला ...? – SymbolixAU

8
x[x[,.N, by=id][,cumsum(N)], status := status * time <=7] 

अगर मैं गलत नहीं हूँ, यह कोई शामिल हो जाता है x[,.N, by=id][,cumsum(N)] के रूप में रिटर्न की पंक्ति-सूचकांक प्रति समूह अंतिम तत्व।

अपडेट: इस एक ही विजेता लगता है और पहली

सूचीबद्ध किया जाना चाहिए यह जो पता चला है सभी सुझाव दिया समाधान की धीमी होने के लिए मेरी प्रारंभिक प्रयास किया गया था गति तुलना देखने के बाद

x[,status := c(.SD[-.N, status], .SD[.N, status * time <=7]), by=id] 
+2

एक चीज जो हमेशा मुझे आश्चर्यचकित करती है वह कितना लचीला 'data.table' है जो कई समाधानों की अनुमति देता है! – SymbolixAU

+1

क्या आपके पास असमानता अभिव्यक्ति गलत तरीके से है? – SymbolixAU

+0

यह बहुत अच्छा है, बिल्कुल जरूरी था। – user2506086

5

एक और प्रयास:

x[ x[,.I==.I[which.max(time)], by=id]$V1 & time > 7, status := FALSE] 
x 

# id time status 
#1: 1 5 FALSE 
#2: 1 6 TRUE 
#3: 2 7 FALSE 
#4: 2 8 FALSE 
3

यहाँ एक और तरीका, ओ पी 'के समान है रों:

y = unique(x[,c("id","time"), with=FALSE], by="id", fromLast=TRUE) 
x[y[time > 7], status := FALSE] 

यहाँ एक और बेंचमार्क है:

n_id = 1e3; n_col = 100; n_draw = 5 

set.seed(1) 
X = data.table(id = 1:n_id)[, .(
    time = sample(10,n_draw), 
    status = sample(c(T,F), n_draw, replace=TRUE) 
), by=id][, paste0("V",1:n_col) := 0] 
setkey(X,id,time) 

X1 = copy(X); X2 = copy(X); X3 = copy(X); X4 = copy(X) 
X5 = copy(X); X6 = copy(X); X7 = copy(X); X8 = copy(X) 

library(microbenchmark) 
library(multcomp) 

microbenchmark(
unique = { 
    Y = unique(X1[,c("id","time"), with=FALSE], by="id", fromLast=TRUE) 
    X1[Y[time > 7], status := FALSE] 
}, 
OP = { 
    y <- X2[,.SD[.N],by=id] 
    X2[y,status:=status & time > 7] 
}, 
Floo0a = X3[,status := c(.SD[-.N, status], .SD[.N, status * time >7]), by=id], 
Floo0b = X4[X4[,.N, by=id][,cumsum(N)], status := status * time >7], 
tlm = X5[ X5[,.I==.I[which.max(time)], by=id]$V1 & time > 7, status := FALSE], 
Symbolix=X6[ X6[order(time), .I[.N], by=id]$V1 , status := ifelse(time > 7, FALSE, TRUE)], 
Frank1 = { 
    y <- X7[, .SD[.N, .(time, status)], by=id][time > 7 & status] 
    X7[y, status := FALSE] 
}, 
Frank2 = { 
    y <- X8[, .SD[.N], by=id][time > 7 & status] 
    X8[y, status := FALSE] 
}, times = 1, unit = "relative") 

परिणाम:

 expr  min   lq  mean  median   uq  max neval 
    unique 1.348592 1.348592 1.348592 1.348592 1.348592 1.348592  1 
     OP 35.048724 35.048724 35.048724 35.048724 35.048724 35.048724  1 
    Floo0a 416.175654 416.175654 416.175654 416.175654 416.175654 416.175654  1 
    Floo0b 1.000000 1.000000 1.000000 1.000000 1.000000 1.000000  1 
     tlm 2.151996 2.151996 2.151996 2.151996 2.151996 2.151996  1 
Symbolix 1.770835 1.770835 1.770835 1.770835 1.770835 1.770835  1 
    Frank1 404.045660 404.045660 404.045660 404.045660 404.045660 404.045660  1 
    Frank2 36.603303 36.603303 36.603303 36.603303 36.603303 36.603303  1 
संबंधित मुद्दे