2015-10-07 15 views
11

समस्या जो मैं हल करने का प्रयास कर रहा हूं वह यह है कि मेरे पास एक क्रमबद्ध POSIXct चर के साथ डेटा फ्रेम है। प्रत्येक पंक्ति को वर्गीकृत किया जाता है और मैं प्रत्येक स्तर के लिए प्रत्येक पंक्ति के बीच समय अंतर प्राप्त करना चाहता हूं और उस डेटा को एक नए चर में जोड़ना चाहता हूं। पुनरुत्पादित समस्या नीचे दी गई है। नीचे दिया गया फ़ंक्शन इस प्रश्न के उद्देश्य के लिए यादृच्छिक समय के साथ नमूना डेटा बनाने के लिए है।एक पंक्ति और डेटा की पिछली पंक्ति के बीच समय अंतर की गणना कैसे करें

random.time <- function(N, start, end) { 
    st <- as.POSIXct(start) 
    en <- as.POSIXct(end) 
    dt <- as.numeric(difftime(en, st, unit="sec")) 
    ev <- sort(runif(N, 0, dt)) 
    rt <- st + ev 
    return(rt) 
} 

समस्या का अनुकरण के लिए कोड के रूप में नीचे है:

set.seed(123) 
category <- sample(LETTERS[1:5], 20, replace=TRUE) 
randtime <- random.time(20, '2015/06/01 08:00:00', '2015/06/01 18:00:00') 
df <- data.frame(category, randtime) 

उम्मीद डेटा फ्रेम जिसके परिणामस्वरूप के रूप में नीचे है:

>category randtime timediff (secs) 
>A 2015-06-01 09:05:00 0 
>A 2015-06-01 09:06:30 90 
>A 2015-06-01 09:10:00 210 
>B 2015-06-01 10:18:58 0 
>B 2015-06-01 10:19:58 60 
>C 2015-06-01 08:14:00 0 
>C 2015-06-01 08:16:30 150 

उत्पादन में प्रत्येक उपसमूह पहली पंक्ति होगा 0 के timediff मूल्य के साथ कोई पिछली पंक्ति नहीं है। मैं श्रेणी के अनुसार समूह करने में सक्षम था और मतभेदों की गणना करने के लिए निम्नलिखित फ़ंक्शन को कॉल करने में सक्षम था लेकिन सभी श्रेणी समूहों के लिए अंतिम आउटपुट को एकत्रित नहीं कर सका।

getTimeDiff <- function(x) { 
    no_rows <- nrow(x) 
    if(no_rows > 1) { 
    for(i in 2:no_rows) { 
     t <- x[i, "randtime"] - x[i-1, "randtime"] 
    } 
    } 
} 

मैं बिना किसी किस्मत के दो दिनों के लिए रहा हूं, इसलिए किसी भी मदद की सराहना करता हूं। धन्यवाद।

उत्तर

10

इस प्रयास करें:

library(dplyr) 
df %>% 
    arrange(category, randtime) %>% 
    group_by(category) %>% 
    mutate(diff = randtime - lag(randtime), 
     diff_secs = as.numeric(diff, units = 'secs')) 

# category   randtime    diff diff_secs 
#  (fctr)    (time)   (dfft)  (dbl) 
# 1  A 2015-06-01 11:10:54   NA hours   NA 
# 2  A 2015-06-01 15:35:04 4.402785 hours 15850.027 
# 3  A 2015-06-01 17:01:22 1.438395 hours 5178.222 
# 4  B 2015-06-01 08:14:46   NA hours   NA 
# 5  B 2015-06-01 16:53:43 518.955379 hours 1868239.364 
# 6  B 2015-06-01 17:37:48 44.090950 hours 158727.420 

तुम भी श्रृंखला के लिए replace(is.na(.), 0) जोड़ सकते हैं।

+0

धन्यवाद। यह आवश्यक रूप से आउटपुट की व्यवस्था में आंशिक रूप से हल करता है। हालांकि अंतराल() पिछली पंक्ति के समय को timediff मान के रूप में देता है और वास्तविक अंतर नहीं। – Mntester

+0

@Mntester तय। – JasonAizkalns

9

आधार आर में आप उपयोग कर सकते हैं:

# creating an ordered data.frame 
df <- data.frame(category, randtime) 
df <- df[order(df$category, df$randtime),] 
# calculating the timedifference 
df$tdiff <- unlist(tapply(df$randtime, INDEX = df$category, 
          FUN = function(x) c(0, `units<-`(diff(x), "secs")))) 

जो देता है:

> df 
    category   randtime  tdiff 
6   A 2015-06-01 11:10:54  0.0000 
15  A 2015-06-01 15:35:04 15850.0271 
18  A 2015-06-01 17:01:22 5178.2223 
1   B 2015-06-01 08:14:46  0.0000 
17  B 2015-06-01 16:53:43 31137.3227 
19  B 2015-06-01 17:37:48 2645.4570 
3   C 2015-06-01 10:09:50  0.0000 
7   C 2015-06-01 12:46:40 9409.9693 
9   C 2015-06-01 13:56:29 4188.4578 
10  C 2015-06-01 14:24:18 1669.1326 
12  C 2015-06-01 14:54:25 1807.1447 
14  C 2015-06-01 15:05:07 641.7068 
2   D 2015-06-01 09:28:16  0.0000 
13  D 2015-06-01 14:55:40 19644.8313 
4   E 2015-06-01 10:18:58  0.0000 
5   E 2015-06-01 10:53:29 2071.2223 
8   E 2015-06-01 13:26:26 9176.6263 
11  E 2015-06-01 14:33:25 4019.0319 
16  E 2015-06-01 15:57:16 5031.4183 
20  E 2015-06-01 17:56:33 7156.8849 

आप मिनट या घंटे चाहते हैं, आप के बजाय "secs""mins" या "hours" उपयोग कर सकते हैं।


data.table पैकेज के साथ एक वैकल्पिक:

library(data.table) 
# creating an ordered/keyed data.table 
dt <- data.table(category, randtime, key = c("category", "randtime")) 
# calculating the timedifference 
dt[, tdiff := difftime(randtime, shift(randtime, fill=randtime[1L]), units="secs"), by=category] 
# or: 
dt[, tdiff := c(0, `units<-`(diff(randtime), "secs")), by = category] 

जिसमें परिणाम: त्वरित प्रतिक्रिया के लिए

> dt 
    category   randtime   tdiff 
1:  A 2015-06-01 11:10:54  0.0000 secs 
2:  A 2015-06-01 15:35:04 15850.0271 secs 
3:  A 2015-06-01 17:01:22 5178.2223 secs 
4:  B 2015-06-01 08:14:46  0.0000 secs 
5:  B 2015-06-01 16:53:43 31137.3227 secs 
6:  B 2015-06-01 17:37:48 2645.4570 secs 
7:  C 2015-06-01 10:09:50  0.0000 secs 
8:  C 2015-06-01 12:46:40 9409.9693 secs 
9:  C 2015-06-01 13:56:29 4188.4578 secs 
10:  C 2015-06-01 14:24:18 1669.1326 secs 
11:  C 2015-06-01 14:54:25 1807.1447 secs 
12:  C 2015-06-01 15:05:07 641.7068 secs 
13:  D 2015-06-01 09:28:16  0.0000 secs 
14:  D 2015-06-01 14:55:40 19644.8313 secs 
15:  E 2015-06-01 10:18:58  0.0000 secs 
16:  E 2015-06-01 10:53:29 2071.2223 secs 
17:  E 2015-06-01 13:26:26 9176.6263 secs 
18:  E 2015-06-01 14:33:25 4019.0319 secs 
19:  E 2015-06-01 15:57:16 5031.4183 secs 
20:  E 2015-06-01 17:56:33 7156.8849 secs 
+0

हां, ये दोनों समाधान महान काम करते हैं। बहुत बहुत धन्यवाद, आप सभी। – Mntester

+0

@Mntester ने आधार आर समाधान – Jaap

+0

के साथ उत्तर बढ़ाया है इच्छा है कि मेरे पास एक से अधिक अपवोट, ऐसे अच्छे, साफ 'डेटा.table' समाधान हो सकते हैं! नोट 'first_removed <- dt [dt [, -.I [1], द्वारा = श्रेणी] $ V1]' परिणामी डेटा.table से प्रति श्रेणी की पहली पंक्ति को हटाने के लिए यदि आवश्यक हो तो उपयोग करें (मेरे मामले में मैं इसका उपयोग कर रहा हूं एक सुविधा के रूप में अंतर, तो मुझे शून्य नहीं चाहिए)। – Bar

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