2012-07-22 15 views
5

मैं प्रत्येक कॉलम में एक अलग फ़ंक्शन लागू करने, समय अंतराल द्वारा डेटा फ्रेम एकत्र करना चाहता हूं। मुझे लगता है कि मेरे पास लगभग aggregate नीचे है, और chron पैकेज के साथ अंतराल में अपना डेटा बांटा है, जो कि काफी आसान था।आर: कॉलम-विशिष्ट फ़ंक्शन के साथ कुल

लेकिन मुझे यकीन नहीं है कि सबसेट को कैसे संसाधित किया जाए। सभी मैपिंग फ़ंक्शंस, *apply, *ply, एक फ़ंक्शन लें (मैं ऐसी चीज की उम्मीद कर रहा था जो प्रति कॉलम लागू करने के लिए फ़ंक्शन का वेक्टर लेता था या उपलब्ध नहीं था, लेकिन एक नहीं मिला) इसलिए मैं एक ऐसा फ़ंक्शन लिख रहा हूं जो लेता है मेरा डेटा फ्रेम सबसेट, और मुझे "समय" को छोड़कर सभी चर के लिए मतलब देता है, जो इंडेक्स है, और "रनऑफ" जो योग होना चाहिए।

मैं इस कोशिश की:

aggregate(d., list(Time=trunc(d.$time, "00:10:00")), function (dat) with(dat, 
list(Time=time[1], mean(Port.1), mean(Port.1.1), mean(Port.2), mean(Port.2.1), 
mean(Port.3), mean(Port.3.1), mean(Port.4), mean(Port.4.1), Runoff=sum(Port.5)))) 

जो बदसूरत पर्याप्त भले ही वह मुझे इस त्रुटि नहीं दिया होगा:

Error in eval(substitute(expr), data, enclos = parent.frame()) : 
    not that many frames on the stack 

जो मुझसे कहता है मैं वास्तव में कुछ गलत कर रहा हूँ। मैंने आर के बारे में जो देखा है, उससे मुझे लगता है कि ऐसा करने का एक शानदार तरीका होना चाहिए, लेकिन यह क्या है?

dput:

d. <- structure(list(time = structure(c(15030.5520833333, 15030.5555555556, 
15030.5590277778, 15030.5625, 15030.5659722222), format = structure(c("m/d/y", 
"h:m:s"), .Names = c("dates", "times")), origin = structure(c(1, 
1, 1970), .Names = c("month", "day", "year")), class = c("chron", 
"dates", "times")), Port.1 = c(0.359747, 0.418139, 0.417459, 
0.418139, 0.417459), Port.1.1 = c(1.3, 11.8, 11.9, 12, 12.1), 
    Port.2 = c(0.288837, 0.335544, 0.335544, 0.335544, 0.335544 
    ), Port.2.1 = c(2.3, 13, 13.2, 13.3, 13.4), Port.3 = c(0.253942, 
    0.358257, 0.358257, 0.358257, 0.359002), Port.3.1 = c(2, 
    12.6, 12.7, 12.9, 13.1), Port.4 = c(0.352269, 0.410609, 0.410609, 
    0.410609, 0.410609), Port.4.1 = c(5.9, 17.5, 17.6, 17.7, 
    17.9), Port.5 = c(0L, 0L, 0L, 0L, 0L)), .Names = c("time", 
"Port.1", "Port.1.1", "Port.2", "Port.2.1", "Port.3", "Port.3.1", 
"Port.4", "Port.4.1", "Port.5"), row.names = c(NA, 5L), class = "data.frame") 

उत्तर

8

आपके दृष्टिकोण के साथ बहुत सी चीजें गलत हैं। सलाह का एक सामान्य टुकड़ा सीधे आपके कथन की तरह दिखने के लिए सीधे नहीं जाना है, लेकिन चीजों को वेतन वृद्धि में काम करना है, अन्यथा यह डीबगिंग (समझ और त्रुटियों को ठीक करने) को काफी कठिन बनाता है। कुछ अपने विभाजन चर के साथ कुछ गड़बड़ है सूचना के लिए

aggregate(d., list(Time=trunc(d.$time, "00:10:00")), identity) 

:

उदाहरण के लिए, आप के साथ शुरू किया जा सकता था। स्पष्ट रूप से aggregate डेटा के इस वर्ग के साथ काम करना पसंद नहीं करता है। आप सांख्यिक को Time परिवर्तित करके इस समस्या को ठीक कर सकते हैं:

aggregate(d., list(Time=as.numeric(trunc(d.$time, "00:10:00"))), identity) 

तो फिर तुम

aggregate(d., list(Time=as.numeric(trunc(d.$time, "00:10:00"))), apply.fun) 

कोशिश कर सकते हैं जहां apply.fun अपने उपयोगकर्ता परिभाषित समारोह है। यह एक नहीं बल्कि criptic संदेश के साथ विफल रहता है, लेकिन

aggregate(d., list(Time=as.numeric(trunc(d.$time, "00:10:00"))), print) 

चल मदद करता है पता है कि aggregate अंदर FUN समारोह प्रत्येक डेटा टुकड़े के लिए एक बार नहीं बुलाया जाता है (और एक data.frame पारित कर दिया), लेकिन यह प्रत्येक स्तंभ के लिए एक बार कहा जाता है आपके डेटा टुकड़ों (और एक अज्ञात वेक्टर पारित) के लिए, इसलिए aggregate का उपयोग करके आप जिस परिणाम को प्राप्त करना चाहते हैं उसे प्राप्त करने का कोई तरीका नहीं है।

इसके बजाय, आप plyr पैकेज से ddply फ़ंक्शन का उपयोग कर सकते हैं। वहां, प्रत्येक टुकड़े पर लागू फ़ंक्शन डेटा प्राप्त करता है।फ्रेम ताकि आप कुछ इस तरह कर सकते हैं:

apply.fun <- function(dat) with(dat, data.frame(Time=time[1], 
               mean(Port.1), 
               mean(Port.1.1), 
               mean(Port.2), 
               mean(Port.2.1), 
               mean(Port.3), 
               mean(Port.3.1), 
               mean(Port.4), 
               mean(Port.4.1), 
               Runoff=sum(Port.5))) 

d.$Time <- as.numeric(trunc(d.$time, "00:10:00")) 
library(plyr) 
ddply(d., "Time", apply.fun) 

#   Time mean.Port.1. mean.Port.1.1. mean.Port.2. mean.Port.2.1. 
# 1 15030.5520833 0.4061886   9.82 0.3262026   11.04 
# mean.Port.3. mean.Port.3.1. mean.Port.4. mean.Port.4.1. Runoff 
# 1  0.337543   10.66  0.398941   15.32  0 

संपादित करें: नीचे पहली टिप्पणी में @roysc सवाल पर अनुवर्ती, आप कर सकते हैं:

apply.fun <- function(dat) { 
    out <- as.data.frame(lapply(dat, mean)) 
    out$Time <- dat$time[1] 
    out$Runoff <- sum(dat$Port.5) 
    return(out) 
} 
+0

ठीक है, मुझे लगता है कि मैं इसे थोड़ा बेहतर समझता हूं। मैं दृढ़ता से टाइप की गई भाषाओं के लिए प्रयोग किया जाता हूं और आर की कक्षा-जबरन योजना को भ्रमित कर रहा हूं। मैं यह भी जानना चाहूंगा कि क्या अधिकांश कॉलम का मतलब लेने का एक आसान तरीका है, लेकिन स्पष्ट रूप से इसे किए बिना, विशेष रूप से इसका इलाज करें। क्या मुझे डीएफ को अलग करना होगा और फिर स्तंभों को फिर से संयोजित करना होगा? – scry

1

कैसे इस बारे में?

library(plyr) 
ddply(d., .(time), colMeans) 
+0

यह इस तथ्य को याद करता है कि कॉलम में से एक का मतलब नहीं होना चाहिए, बल्कि योग – Chase

+0

मैंने देखा कि अधिक उपयोगी उत्तर आते हैं। मैं इसे अपडेट करूंगा। – Maiasaura

5

उपयोग by बजाय aggregate

तो f कि list को छोड़कर अपने गुमनाम समारोह के रूप में Samee है के भीतर यह इतना है कि f <- function(dat) with(dat, data.frame(...whatever...)) तो data.frame साथ बदल दिया है:

d.by <- by(d., list(Time = trunc(d.$time, "00:10:00")), f) 
d.rbind <- do.call("rbind", d.by) # bind rows together 

# fix up row and column names 
rownames(d.rbind) <- NULL 
colnames(d.rbind) <- colnames(d.) 

हम पिछले बयान उसमें कॉलम के नाम अगर f जोड़ा नाम ही प्रदान करती है को दूर कर सकता है सिर्फ Time के बजाय।

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