日付の降順に並べられたデータフレームがあります。
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')
)
UserIDの最初の行にNAが含まれている場合、NA値を以前の値に置き換え(ユーザーIDでグループ化)、そのuseridグループの次の値セットに置き換えます。
私はこのような何かをdplyrとZooパッケージを使用しようとしています...しかし、それは動作しません
cleanedFUG <- filteredUserGroup %>%
group_by(UserID) %>%
mutate(Age1 = na.locf(Age),
Color1 = na.locf(Color),
Gender1 = na.locf(Gender) )
次のような結果dfが必要です。
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
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
Data.frame全体でZoo::na.locf
を直接使用すると、userID
グループに関係なくNAがいっぱいになります。パッケージdplyrのグループ化は、残念ながらna.locf
関数には影響しません。そのため、私は分割を行いました。
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
それは、最初にデータを3つのdata.framesに分割し、次に補完の最初のパス(下向き)を適用し、次にlapply
の匿名関数で上向きに適用し、最終的にrbind
を使用してdata.framesを元に戻します。期待どおりの出力が得られました。
purrr
と組み合わせたna.locf()
で@agenisメソッドを使用すると、次のことができます。
library(purrr)
library(Zoo)
ps1 %>%
slice_rows("userID") %>%
by_slice(function(x) {
na.locf(na.locf(x), fromLast=T) },
.collate = "rows")
この関数を作成しましたが、fillよりも確実に高速であり、おそらくna.locfよりも高速です。
fill_NA <- function(x) {
which.na <- c(which(!is.na(x)), length(x) + 1)
values <- na.omit(x)
if (which.na[1] != 1) {
which.na <- c(1, which.na)
values <- c(values[1], values)
}
diffs <- diff(which.na)
return(rep(values, times = diffs))
}