我有一个由三列组成的数据框(参见代码中的示例)。第一列包含类别(a),第二列包含观察数(b),第三列包含这些观察的平均值(c)。
#create a test df
a<-factor(c("aaa","aaa","aaa","ddd","eee","ddd","aaa","ddd"))
b<-c(3,4,1,3,5,7,3,2)
c<-c(1,2,NA,4,5,6,7,NA)
df.abc<-data.frame(a=a,b=b,c=c)
df.abc
如果观察次数为1或2,则标记为缺失值的条目(NA)。
因此,我的功能的目的是用每个类别的平均值替换这些缺失值。
我接过了我,但是我有一个功能正常工作,用一个类别的所有缺失值替换(如果观察结果为1)。它看起来像这样:
#function to substitue the missing values in row c by their means
#according to their categories
function.abc<-function(x){
ifelse(
(df.abc[,1]==x)&(df.abc[,2]==1),
mean(df.abc$c[df.abc$a ==x],na.rm=TRUE),
df.abc[,3]
)
}
测试此功能:
#test the function for the category "ccc"
function.abc("aaa")
效果很好(但只是平均值而不是平均值)输出为:
[1] 1.000000 2.000000 3.333333 4.000000 5.000000 6.000000 7.000000 NA
现在我的问题是,我有很多类别(n = 32),我试图在包含我的类别的向量上应用此函数。在这种情况下,一个简单的例子是:
#test the function for a testvector
test.vector<-c("aaa","ddd")
function.abc(test.vector)
输出是:
[1] 1.0 2.0 4.5 4.0 5.0 6.0 7.0 NA
显然这不会有效......
有人可以帮我重新安排功能吗?我对编程很陌生,设计简短和良好的功能对我来说仍然是一个很大的挑战......
修改
我希望输出为: [1] 1.000000 2.000000 3.20000 4.000000 5.000000 6.000000 7.000000 5.000000
使组aaa(3.20000)的平均值代替aaa中的NA值,组ddd(5.0000000)的平均值代替ddd中的NA ...
答案 0 :(得分:1)
为了在一个类别中同时处理多个列,您需要使用分割数据帧然后处理组件的东西。 lapply( split(df, fac), function(x) {...})
范例适用于此。或者您可以使用transform
或plyr
包。
> lapply( split( df.abc, df.abc$a),
function(dfrm) { dfrm[is.na(dfrm$c), "c"] <-
weighted.mean(dfrm[!is.na(dfrm$c) , "c"], dfrm[!is.na(dfrm$c), "b"])
dfrm} )
# need to evaluate dfrm in order to return the full value.
$aaa
a b c
1 aaa 3 1.0
2 aaa 4 2.0
3 aaa 1 3.2
7 aaa 3 7.0
$ddd
a b c
4 ddd 3 4.0
6 ddd 7 6.0
8 ddd 2 5.4
$eee
a b c
5 eee 5 5
然后您可以使用`do.call:
rbind
do.call( rbind, lapply( split( df.abc, df.abc$a),
function(dfrm) { dfrm[is.na(dfrm$c), "c"] <-
weighted.mean(dfrm[!is.na(dfrm$c) , "c"], dfrm[!is.na(dfrm$c), "b"])
dfrm} ) )
a b c
aaa.1 aaa 3 1.0
aaa.2 aaa 4 2.0
aaa.3 aaa 1 3.2
aaa.7 aaa 3 7.0
ddd.4 ddd 3 4.0
ddd.6 ddd 7 6.0
ddd.8 ddd 2 5.4
eee eee 5 5.0
答案 1 :(得分:0)
我不太清楚你的意思,但如果你想包含所有这些行,你可以使用%in%。
function.abc<-function(x){
ifelse(
(df.abc[,1] %in% x)&(df.abc[,2]==1),
mean(df.abc$c[df.abc$a %in% x],na.rm=TRUE),
df.abc[,3]
)
}
> function.abc("aaa")
[1] 1.000000 2.000000 3.333333 4.000000 5.000000 6.000000 7.000000 NA
> test.vector<-c("aaa","ddd")
> function.abc(test.vector)
[1] 1 2 4 4 5 6 7 NA
最后一个元素是NA,因为列'b'不是1。
答案 2 :(得分:0)
CatMeans <- tapply(df.abc$c, df.abc$a, function(x) mean(x, na.rm==T))
将按类别为您提供方法。
aaa ddd eee
3.333333 5.000000 5.000000
为所有这些人做这件事:
> CatMeans <- tapply(df.abc$c, df.abc$a, function(x) mean(x, na.rm==T))
> ifelse(is.na(df.abc$c), CatMeans[df.abc$a], df.abc$c)
[1] 1.000000 2.000000 3.333333 4.000000 5.000000 6.000000 7.000000 5.000000
你可以把它变成一个我敢肯定的功能。如果您只想"aaa"
和"ddd"
,那么您可以ifelse(is.na(df.abc$c) & df.abc$a %in% c("aaa","ddd"),...