我有一个数据框(df),其中包含4列值(V1到V4列),我需要根据另外两列(最大和最小列)进行选择。我的目标是将NAs分配给超出每行最大和最小列设置范围的值,并计算剩余值的平均值。
V1 V2 V3 V4 max min
1 3 6 8 7 5
23 30 5 17 30 16
预期输出为:
V1 V2 V3 V4 max min mean
NA NA 6 NA 7 5 6
23 30 NA 17 30 16 35
到目前为止,我只能通过使用以下脚本来分配NAs ...
df$V1 <- ifelse(df$V1 > df$max | df$V1 < df$min, NA, df$V1)
df$V2 <- ifelse(df$V2 > df$max | df$V2 < df$min, NA, df$V2)
df$V3 <- ifelse(df$V3 > df$max | df$V3 < df$min, NA, df$V3)
df$V4 <- ifelse(df$V4 > df$max | df$V4 < df$min, NA, df$V4)
...然后以下计算平均值:
df$mean <- rowMeans(df[, 1:4], na.rm = TRUE)
问题在于,实际数据中的列数将远大于4,并且此方法似乎需要过多的重复。在R中有更好的方法吗?
我尝试使用data.table
对有效值进行分组,然后使用apply
函数而不成功:
df <- df[df[,1:4] <= df$max | df[,1:4] >= df$min, ]
apply(df[,1:4], 1, function(x) mean(x))
谢谢。
答案 0 :(得分:2)
例如,您可以尝试以下方法,首先解压缩数据。
# getting your data:
df <- read.table(text="V1 V2 V3 V4 max min
1 3 6 8 7 5
23 30 5 17 30 16", header=T)
# melting the data:
library(reshape2)
df2 <- melt(df, id.vars = c("max", "min"))
df2
max min variable value
1 7 5 V1 1
2 30 16 V1 23
3 7 5 V2 3
4 30 16 V2 30
5 7 5 V3 6
6 30 16 V3 5
7 7 5 V4 8
8 30 16 V4 17
# I create a new vector with NAs, but you could easily just overwrite the values:
df2$val <- with(df2, ifelse(value > max | value < min, NA, value))
# Cast the data into the old form again.
df3 <- dcast(df2, max + min ~ variable, value.var = "val")
# calculate the rowMeans:
df3$mean <- rowMeans(df3[, 3:6], na.rm = TRUE)
# Doing some cosmetics here to get the same column ordering. Chose your preferred way or rearranging the columns, if required at all.
df3 <- df3[, c(paste0("V", 1:4),"max", "min", "mean") ]
df3
V1 V2 V3 V4 max min mean
1 NA NA 6 NA 7 5 6.00000
2 23 30 NA 17 30 16 23.33333
请注意,唯一的区别是第二行的平均值较低。我不确定你的价值是多少35。
答案 1 :(得分:1)
尝试:
df <- read.table(header=TRUE, text="V1 V2 V3 V4 max min
1 3 6 8 7 5
23 30 5 17 30 16")
df.new<-apply(df[,1:4],2,function(x) ifelse(x>df[,5] | x<df[,6],NA,x))
df.new<-cbind(df.new,df[,5:6])
df.new$mean=rowMeans(df.new[1:4],na.rm=TRUE)
df.new
答案 2 :(得分:1)
这是一个简单的解决方案,其中for
循环用于填充NA,rowMeans
用于计算每行的平均值。
# loop through rows and fill in NA for values outside of min/max
for(i in 1:nrow(df))
is.na(df[i, 1:4]) <- df[i, 1:4] < df[i, "min"] | df[i, 1:4] > df[i, "max"]
# calculate mean of each row
df$mean <- rowMeans(df[, 1:4], na.rm=TRUE)
返回
df
V1 V2 V3 V4 max min mean
1 NA NA 6 NA 7 5 6.00000
2 23 30 NA 17 30 16 23.33333