为什么不变异填充所有行?正在使用 mutate 和 ifelse 从另一个数据框中查找估算值
Why didn't mutate fill all rows? Was using mutate and ifelse to look up imputed values from another dataframe
这是交易。试图使用 plyr
包中的 mutate
从另一个数据帧中查找适当的值,如果原始数据帧中的 v
变量是 NA
。查找的值应该进入一个新变量 imputed
。我还为此查找目的定义了一个自定义函数。
代码如下:
if(!require(plyr)){
install.packages("plyr")
library(plyr)
}
df = data.frame(d=c(1,1,1,2,2,2,3,3,3),
g=rep(c(1,2,3),3),
v=c(5,NA,NA,5,NA,NA,5,NA,NA))
imputed = data.frame(g=c(1,2,3),
v=c(5,10,15))
getImputed = function(p){
imputed[imputed$g==p,"v"]
}
df = mutate(df,imputed=ifelse(is.na(v),getImputed(g),v))
df
这是生成的数据帧:
d g v imputed
1 1 1 5 5
2 1 2 NA 10
3 1 3 NA 15
4 2 1 5 5
5 2 2 NA NA
6 2 3 NA NA
7 3 1 5 5
8 3 2 NA NA
9 3 3 NA NA
可以看到,mutate 只成功填充了前 3 行。 ifelse
函数很可能是问题所在,但我不明白为什么:(
奇怪的是,如果 imputed
数据框有 4 行,像这样:
imputed = data.frame(g=c(1,2,3,4),
v=c(5,10,15,20))
然后 df
数据框被正确填充:
d g v imputed
1 1 1 5 5
2 1 2 NA 10
3 1 3 NA 15
4 2 1 5 5
5 2 2 NA 10
6 2 3 NA 15
7 3 1 5 5
8 3 2 NA 10
9 3 3 NA 15
但是 R 给了我一个警告说:
Warning message:
In imputed$g == p :
longer object length is not a multiple of shorter object length
我是不是忽略了什么?
问题出在您的 getImputed
函数上。 mutate
函数不会遍历行。它将列作为向量传递给函数,因此每个函数基本上都称为一个。如果您传递单个值,您的 getInputed
函数可以工作,但对于向量
则效果不佳
getImputed(1)
# [1] 5
getImputed(c(1,2))
# [1] 5 10
# Warning message:
# In imputed$g == p :
# longer object length is not a multiple of shorter object length
编写函数的更好方法是
getImputed2 <- function(p){
imputed$v[match(p, imputed$g)]
}
这将正确处理值向量
mutate(df,imputed=ifelse(is.na(v),getImputed2(g),v))
# d g v imputed
# 1 1 1 5 5
# 2 1 2 NA 10
# 3 1 3 NA 15
# 4 2 1 5 5
# 5 2 2 NA 10
# 6 2 3 NA 15
# 7 3 1 5 5
# 8 3 2 NA 10
# 9 3 3 NA 15
你也可以考虑加入和替换
mutate(join(df, setNames(imputed, c("g","v2")), by=c(g="g")),
v=ifelse(is.na(v), v2, v), v2=NULL)
这是交易。试图使用 plyr
包中的 mutate
从另一个数据帧中查找适当的值,如果原始数据帧中的 v
变量是 NA
。查找的值应该进入一个新变量 imputed
。我还为此查找目的定义了一个自定义函数。
代码如下:
if(!require(plyr)){
install.packages("plyr")
library(plyr)
}
df = data.frame(d=c(1,1,1,2,2,2,3,3,3),
g=rep(c(1,2,3),3),
v=c(5,NA,NA,5,NA,NA,5,NA,NA))
imputed = data.frame(g=c(1,2,3),
v=c(5,10,15))
getImputed = function(p){
imputed[imputed$g==p,"v"]
}
df = mutate(df,imputed=ifelse(is.na(v),getImputed(g),v))
df
这是生成的数据帧:
d g v imputed
1 1 1 5 5
2 1 2 NA 10
3 1 3 NA 15
4 2 1 5 5
5 2 2 NA NA
6 2 3 NA NA
7 3 1 5 5
8 3 2 NA NA
9 3 3 NA NA
可以看到,mutate 只成功填充了前 3 行。 ifelse
函数很可能是问题所在,但我不明白为什么:(
奇怪的是,如果 imputed
数据框有 4 行,像这样:
imputed = data.frame(g=c(1,2,3,4),
v=c(5,10,15,20))
然后 df
数据框被正确填充:
d g v imputed
1 1 1 5 5
2 1 2 NA 10
3 1 3 NA 15
4 2 1 5 5
5 2 2 NA 10
6 2 3 NA 15
7 3 1 5 5
8 3 2 NA 10
9 3 3 NA 15
但是 R 给了我一个警告说:
Warning message:
In imputed$g == p :
longer object length is not a multiple of shorter object length
我是不是忽略了什么?
问题出在您的 getImputed
函数上。 mutate
函数不会遍历行。它将列作为向量传递给函数,因此每个函数基本上都称为一个。如果您传递单个值,您的 getInputed
函数可以工作,但对于向量
getImputed(1)
# [1] 5
getImputed(c(1,2))
# [1] 5 10
# Warning message:
# In imputed$g == p :
# longer object length is not a multiple of shorter object length
编写函数的更好方法是
getImputed2 <- function(p){
imputed$v[match(p, imputed$g)]
}
这将正确处理值向量
mutate(df,imputed=ifelse(is.na(v),getImputed2(g),v))
# d g v imputed
# 1 1 1 5 5
# 2 1 2 NA 10
# 3 1 3 NA 15
# 4 2 1 5 5
# 5 2 2 NA 10
# 6 2 3 NA 15
# 7 3 1 5 5
# 8 3 2 NA 10
# 9 3 3 NA 15
你也可以考虑加入和替换
mutate(join(df, setNames(imputed, c("g","v2")), by=c(g="g")),
v=ifelse(is.na(v), v2, v), v2=NULL)