2010-05-05 6 views
10

मैं एक डेटा सेट के लिए "अंतिम निरीक्षण कैर्री फॉरवर्ड" लागू करना चाहता हूं, जिस पर मैं काम कर रहा हूं जिस पर इसके अंत में मूल्य गुम हैं।अंतिम निरीक्षण एक डेटा फ्रेम में आगे बढ़े?

LOCF <- function(x) 
{ 
    # Last Observation Carried Forward (for a left to right series) 
    LOCF <- max(which(!is.na(x))) # the location of the Last Observation to Carry Forward 
    x[LOCF:length(x)] <- x[LOCF] 
    return(x) 
} 


# example: 
LOCF(c(1,2,3,4,NA,NA)) 
LOCF(c(1,NA,3,4,NA,NA)) 

अब इस सरल वैक्टर के लिए महान काम करता है:

यहाँ एक सरल यह करने के लिए (सवाल यह बाद) कोड है। लेकिन अगर मैं डेटा फ्रेम पर इसे आजमाने और उपयोग करने के लिए कहता हूं:

a <- data.frame(rep("a",4), 1:4,1:4, c(1,NA,NA,NA)) 
a 
t(apply(a, 1, LOCF)) # will make a mess 

यह मेरे डेटा फ्रेम को एक चरित्र मैट्रिक्स में बदल देगा।

क्या आप डेटा.फ्रेम पर LOCF करने के तरीके के बारे में सोच सकते हैं, इसे मैट्रिक्स में बदल दिए बिना? (मैं छोरों इस्तेमाल कर सकते हैं और गंदगी को दूर करने के इस तरह के, लेकिन एक और अधिक सुरुचिपूर्ण समाधान के लिए प्यार होता है)

चीयर्स,

ताल

उत्तर

18

यह पहले से मौजूद है:

library(zoo) 
na.locf(data.frame(rep("a",4), 1:4,1:4, c(1,NA,NA,NA))) 
+2

+1 और निश्चित रूप से rseek.org तुरंत पहले परिणाम के रूप में इस पूरी करता है। –

+0

मेरी बोली लगाने के लिए मेरी बोली - धन्यवाद शेन। लेकिन मुझे डर है कि यह नौकरी नहीं करता है। (यह प्रत्येक पंक्ति के बजाय कॉलम 3 भरता है) –

+1

यदि आप '[r] locf' के लिए stackoverflow.com खोजते हैं तो आपको यह भी मिल सकता है। – Shane

0

मैं समाप्त हो गया लूप का उपयोग करके इसे हल करना:

fillInTheBlanks <- function(S) { 
    L <- !is.na(S) 
    c(S[L][1], S[L])[cumsum(L)+1] 
} 


LOCF.DF <- function(xx) 
{ 
    # won't work well if the first observation is NA 

    orig.class <- lapply(xx, class) 

    new.xx <- data.frame(t(apply(xx,1, fillInTheBlanks))) 

    for(i in seq_along(orig.class)) 
    { 
     if(orig.class[[i]] == "factor") new.xx[,i] <- as.factor(new.xx[,i]) 
     if(orig.class[[i]] == "numeric") new.xx[,i] <- as.numeric(new.xx[,i]) 
     if(orig.class[[i]] == "integer") new.xx[,i] <- as.integer(new.xx[,i]) 
    } 

    #t(na.locf(t(a))) 

    return(new.xx) 
} 

a <- data.frame(rep("a",4), 1:4,1:4, c(1,NA,NA,NA)) 
LOCF.DF(a) 
2

यह प्रश्न पुराना है लेकिन पोस्टरिटी के लिए ... सबसे अच्छा समाधान आयन रोल = टी के साथ data.table पैकेज का उपयोग करना है।

+17

उदाहरण के साथ भरें – mnel

0

apply() के बजाय आप lapply() का उपयोग कर सकते हैं और फिर परिणामी सूची को data.frame पर बदल सकते हैं।

LOCF <- function(x) { 
    # Last Observation Carried Forward (for a left to right series) 
    LOCF <- max(which(!is.na(x))) # the location of the Last Observation to Carry Forward 
    x[LOCF:length(x)] <- x[LOCF] 
    return(x) 
} 

a <- data.frame(rep("a",4), 1:4, 1:4, c(1, NA, NA, NA)) 
a 
data.frame(lapply(a, LOCF)) 
4

इस कार्यक्षमता को लागू करने वाले पैकेजों का एक समूह है।

  • अन्तरिक्ष समय :: na.locf
  • imputeTS :: na.locf
  • चिड़ियाघर :: na.locf (समान बुनियादी कार्यक्षमता है, लेकिन अतिरिक्त विकल्प में कुछ मतभेद के साथ)
  • XTS :: na.locf
+1

इसके अलावा tidyverse के बराबर fill() फ़ंक्शन है। डेटाटेबल में कुछ तेज होना बहुत अच्छा होगा। – skan

4

यदि आप na.locf फ़ंक्शन के लिए चिड़ियाघर जैसे बड़े पैकेज को लोड नहीं करना चाहते हैं, तो यहां एक छोटा समाधान है जो इनपुट वेक्टर में कुछ प्रमुख एनएएस होने पर भी काम करता है।

na.locf <- function(x) { 
    v <- !is.na(x) 
    c(NA, x[v])[cumsum(v)+1] 
} 
+0

मुझे यह समाधान सबसे अच्छा लगता है। यदि आप मूल प्रश्न में 'data.frame' पर इसे लागू करना चाहते हैं, तो आप इसे' a [] = lapply (a, na.locf) 'के माध्यम से उपयोग कर सकते हैं। – cryo111

5

एक कॉलम में आगे पिछले प्रेक्षण ले जाने NA रों में भरने के लिए नए tidyr::fill() समारोह जोड़ना:

a <- data.frame(col1 = rep("a",4), col2 = 1:4, 
       col3 = 1:4, col4 = c(1,NA,NA,NA)) 
a 
# col1 col2 col3 col4 
# 1 a 1 1 1 
# 2 a 2 2 NA 
# 3 a 3 3 NA 
# 4 a 4 4 NA 

a %>% tidyr::fill(col4) 
# col1 col2 col3 col4 
# 1 a 1 1 1 
# 2 a 2 2 1 
# 3 a 3 3 1 
# 4 a 4 4 1 
संबंधित मुद्दे