我有一个数据框 (df),其中包含 4 列值(V1 到 V4 列),我需要根据其他两列(最大和最小列)进行选择。我的目标是将 NA 分配给每行的 max 和 min 列设置的范围之外的值,并计算剩余值的平均值。
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
到目前为止,我只能通过使用以下脚本来分配 NA 来做到这一点...
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))
谢谢。
最佳答案
例如,您可以尝试以下方法,首先熔化您的数据。
# 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 的值的。
关于R:根据行范围选择行值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43741371/