2016-10-14 33 views
7

Aşağı inen sıralama düzeniyle bir veri çerçevem ​​var.NA'yı önceki veya sonraki değerle değiştir, grupla, dplyr ile

ps1 = data.frame(userID = c(21,21,21,22,22,22,23,23,23), 
      color = c(NA,'blue','red','blue',NA,NA,'red',NA,'gold'), 
      age = c('3yrs','2yrs',NA,NA,'3yrs',NA,NA,'4yrs',NA), 
      gender = c('F',NA,'M',NA,NA,'F','F',NA,'F') 
) 

Ben NA önceki değerlerine ve kullanıcı kimliği ilk satırı NA o kimliği grup için değerlerin sonraki set ile değiştirin etti durumunda kullanıcı kimliği göre gruplandırılmış ile değerleri impute (replace) istiyoruz.

böyle dplyr ve hayvanat bahçesi paketleri şey kullanmak çalışıyorum ... ama onun ben neden ihtiyaç

cleanedFUG <- filteredUserGroup %>% 
group_by(UserID) %>% 
mutate(Age1 = na.locf(Age), 
    Color1 = na.locf(Color), 
    Gender1 = na.locf(Gender)) 

çalışmıyor df böyle:

     userID color age gender 
       1  21 blue 3yrs  F 
       2  21 blue 2yrs  F 
       3  21 red 2yrs  M 
       4  22 blue 3yrs  F 
       5  22 blue 3yrs  F 
       6  22 blue 3yrs  F 
       7  23 red 4yrs  F 
       8  23 red 4yrs  F 
       9  23 gold 4yrs  F 
+0

bakınız. [NA'ları en son NA olmayan değerlerle değiştirme] (http://stackoverflow.com/questions/7735647/replacing-nas-with-latest-non-na-value) veya bu [NA değerini grup değeriyle değiştirin] (http : //stackoverflow.com/questions/23583739/replace-na-value-with-the-group-value) –

+0

@Tarak merhaba, cevaplardan biri sorununuzu çözerse, "kabul edildi" yi işaretlemekten çekinmeyin. diğer insanlar da bunu görebiliyorlar ... teşekkürler – agenis

cevap

17
require(tidyverse) #fill is part of tidyr 

ps1 %>% 
    group_by(userID) %>% 
    fill(color, age, gender) %>% #default direction down 
    fill(color, age, gender, .direction = "up") 

:

Source: local data frame [9 x 4] 
Groups: userID [3] 

    userID color age gender 
    <dbl> <fctr> <fctr> <fctr> 
1  21 blue 3yrs  F 
2  21 blue 2yrs  F 
3  21 red 2yrs  M 
4  22 blue 3yrs  F 
5  22 blue 3yrs  F 
6  22 blue 3yrs  F 
7  23 red 4yrs  F 
8  23 red 4yrs  F 
9  23 gold 4yrs  F 
1

bütün direkt zoo::na.locf kullanma data.frame, userID grubundan bağımsız olarak NA'yı dolduracaktır. Ben bir bölünme ile gitti neden Paketi dplyr en gruplama na.locf fonksiyonu üzerine maalesef hiçbir etkisi yoktur, işte bu:

library(dplyr); library(zoo) 
ps1 %>% split(ps1$userID) %>% 
    lapply(function(x) {na.locf(na.locf(x), fromLast=T)}) %>% 
    do.call(rbind, .) 
####  userID color age gender 
#### 21.1  21 blue 3yrs  F 
#### 21.2  21 blue 2yrs  F 
#### 21.3  21 red 2yrs  M 
#### 22.4  22 blue 3yrs  F 
#### 22.5  22 blue 3yrs  F 
#### 22.6  22 blue 3yrs  F 
#### 23.7  23 red 4yrs  F 
#### 23.8  23 red 4yrs  F 
#### 23.9  23 gold 4yrs  F 

şey aslında ilk 3 data.frames veri böler olmasıdır, o zaman isnadın ilk geçişini uygulamak (aşağı doğru), daha sonra lapply'daki anonim işlevle yukarı doğru ve sonunda data.frames'leri bir araya getirmek için rbind kullanın. Beklenen çıktınız var. verir

+1

'do.call()' ile daha idiomatik 'bind_rows()' ve 'split (ps1 $ userID)' ile 'split (. $ userID)' yerine –

+1

değiştirin. 'purrr' kullanarak alternatif de olabilir: kütüphane (purrr); % ps1>% slice_rows ("userID")%>% by_slice (işlev (x) {na.locf (na.locf (x), fromLast = T)}, .collate = "satır") ' –

+1

@ StevenBeaupré güzel! Bu kendi başına yeni bir cevap hak ediyor ;-) – agenis

1

purrr ile kombine na.locf() ile yöntemini @agenis kullanarak, yapabileceği: bu yararlı olup olmadığını

library(purrr) 
library(zoo) 

ps1 %>% 
    slice_rows("userID") %>% 
    by_slice(function(x) { 
    na.locf(na.locf(x), fromLast=T) }, 
    .collate = "rows")