2016-02-01 14 views
5

मेरे पास तापमान के दैनिक अवलोकन के साथ समय श्रृंखला डेटा का डेटाफ्रेम है। मुझे एक डमी वैरिएबल बनाने की ज़रूरत है जो प्रत्येक दिन मायने रखती है जिसमें तापमान 5 सी की सीमा से ऊपर है। यह अपने आप में आसान होगा, लेकिन एक अतिरिक्त स्थिति मौजूद है: गिनती केवल थ्रेसहोल्ड के ऊपर लगातार दस दिनों के बाद शुरू होती है। यहाँ एक उदाहरण dataframe है:आर में एक सशर्त डमी कैसे बनाएं?

df <- data.frame(date = seq(365), 
     temp = -30 + 0.65*seq(365) - 0.0018*seq(365)^2 + rnorm(365)) 

मुझे लगता है मैं यह किया गया था, लेकिन मेरी पसंद के लिए भी कई छोरों के साथ। मैंने यही किया:

df$dummyUnconditional <- 0 
df$dummyHead <- 0 
df$dummyTail <- 0 

for(i in 1:nrow(df)){ 
    if(df$temp[i] > 5){ 
     df$dummyUnconditional[i] <- 1 
    } 
} 

for(i in 1:(nrow(df)-9)){ 
    if(sum(df$dummyUnconditional[i:(i+9)]) == 10){ 
     df$dummyHead[i] <- 1 
    } 
} 

for(i in 9:nrow(df)){ 
    if(sum(df$dummyUnconditional[(i-9):i]) == 10){ 
     df$dummyTail[i] <- 1 
    } 
} 

df$dummyConditional <- ifelse(df$dummyHead == 1 | df$dummyTail == 1, 1, 0) 

क्या कोई ऐसा करने के लिए आसान तरीके सुझा सकता है?

उत्तर

5

यहाँ एक आधार आर rle का उपयोग कर विकल्प नहीं है:

df$dummy <- with(rle(df$temp > 5), rep(as.integer(values & lengths >= 10), lengths)) 

कुछ स्पष्टीकरण: कार्य रन लंबाई एन्कोडिंग (rle) समारोह, imo के लिए एक क्लासिक उपयोग है। हम पहले (एक तार्किक वेक्टर बनाने) की जाँच करता है, तो temp का मूल्य 5 से बड़ा है और जिसका परिणाम है कि वेक्टर पर rle लागू होते हैं:

> rle(df$temp > 5) 
#Run Length Encoding 
# lengths: int [1:7] 66 1 1 225 2 1 69 
# values : logi [1:7] FALSE TRUE FALSE TRUE FALSE TRUE ... 

अब हम उन मामलों को खोजने के लिए चाहते हैं, जहां valuesTRUE है (यानी अस्थायी है 5 से अधिक) और जहां एक ही समय में lengths 10 से अधिक है (यानी कम से कम दस लगातार temp मान 5 से अधिक हैं)। हम चल रहा है ऐसा करते हैं:

values & lengths >= 10 

और अंत में, के बाद से हम nrow(df) रूप में एक ही लंबाई की एक सदिश वापस जाने के लिए चाहते हैं, हम क्रम में rep(..., lengths) और as.integer का उपयोग TRUE/FALSE के बजाय 1/0 वापस जाने के लिए।

+1

अन्य दो सुझाव भी काम है, लेकिन यह सबसे सरल था और मैं किसी भी तरह अगर इस तरह से मौजूद है आर आधार समाधान का उपयोग करने के लिए इच्छुक हूँ। धन्यवाद! – Antti

+0

आप इस समाधान की बारीकी से जांच कर सकते हैं। मुझे 67-75 दिनों में डमी मूल्य = 1 मिला, इस तथ्य के बावजूद कि ये दिन लगातार 10 दिन की दौड़ के 5 डिग्री temps – JHowIX

+0

@JHowIX का हिस्सा नहीं हैं, क्या आप इसका उदाहरण दे सकते हैं? ध्यान दें कि नमूना डेटा बीज सेट किए बिना 'rnorm' का उपयोग करता है, इसलिए समाधान आवश्यक नहीं होते हैं (चूंकि नमूना डेटा भिन्न हो सकता है) –

5

मुझे लगता है कि आप एक साधारण ifelse के संयोजन का उपयोग कर सकते हैं और रोल जो आप ढूंढ रहे हैं उसे प्राप्त करने के लिए zoo package में फ़ंक्शन लागू करते हैं। अंतिम चरण में परिणाम को पहले एन -1 दिनों के लिए पैडिंग करना शामिल है जहां खिड़की को भरने के लिए पर्याप्त जानकारी नहीं है।

library(zoo) 

df <- data.frame(date = seq(365), 
       temp = -30 + 0.65*seq(365) - 0.0018*seq(365)^2 + rnorm(365)) 

df$above5 <- ifelse(df$temp > 5, 1, 0) 
temp <- rollapply(df$above5, 10, sum) 
df$conseq <- c(rep(0, 9),temp) 
+1

'एक साधारण के साथ' 'sum' समारोह (एक्स) {(x) योग} की जगह? –

+1

इस तरह इसे लिखने का सुझाव: 'df2 <- परिणत (परिणत (df, uncond = अस्थायी> 5), सिर = rollsum (uncond, 10, align =" left ", भरने = 0) == 10, पूंछ = rollsum (uncond, 10, align = "सही", भरने = 0) == 10) + 0' –

2

मैं यह कर जाएगा:

set.seed(42) 
df <- data.frame(date = seq(365), 
       temp = -30 + 0.65*seq(365) - 0.0018*seq(365)^2 + rnorm(365)) 
thr <- 5 
df$dum <- 0 

#find first 10 consecutive values above threshold 
test1 <- filter(df$temp > thr, rep(1,10), sides = 1) == 10L 
test1[1:9] <- FALSE 
n <- which(cumsum(test1) == 1L) 

#count days above threshold after that 
df$dum[(n+1):nrow(df)] <- cumsum(df$temp[(n+1):nrow(df)] > thr) 
संबंधित मुद्दे