我想知道是否有人有一个很好的方法来实现这一目标.我有一个数据框,其中属于特定组(=条件)的每个观察(=项目)具有给定值:
# Create sample data. item = rep(1:3,2) #6 items condition = c(rep("control",3), rep("related",3)) #2 conditions value = c(10,11,12,20,21,22) #6 values df = data.frame(item, condition, value) item condition value 1 1 control 10 2 2 control 11 3 3 control 12 4 1 related 20 5 2 related 21 6 3 related 22
我还有一个查找表,其中包含每组的平均值:
# Create lookup table. condition = c("control", "related") mean = c(11,21) table = data.frame(condition, mean) condition mean 1 control 11 2 related 21
我想修改我的原始数据帧,使得它包含一个新列label
,其中说:" 低 ",如果该项目的值低于集团平均,而" 高 ",否则.它应该如下所示:
# How the output should look like. # If the item value is less than the group mean, write "low". Write "high" otherwise. item = rep(1:3,2) condition = c(rep("control",3), rep("related",3)) value = c(10,11,12,20,21,22) label = c(rep(c("low", "high", "high"),2)) output = data.frame(item, condition, value, label) item condition value label 1 1 control 10 low 2 2 control 11 high 3 3 control 12 high 4 1 related 20 low 5 2 related 21 high 6 3 related 22 high
如果这只是将组平均值复制到原始数据框中,我会使用merge
.但我需要的是考虑组平均值,为每个项目写一个新标签,根据组平均值显示" 低 "或" 高 ".
我尝试的一件事是首先将我的数据框与表合并,然后用于ifelse
比较value列和mean列.这有效,但我最终在我的数据框中有一个平均列,我不需要(我只需要标签列).当然,我可以手动删除平均列,但看起来很笨重.所以我想知道:有人知道一个更好/更优雅的解决方案吗?
谢谢你!
这是一些替代方案.(1)和(2)仅使用基数R和(2),(3)和(5)不创建仅明确删除的平均列.在(1),(3)和(4)中,我们使用左连接,尽管内连接将给出与该数据相同的结果,并且在(1a)的情况下允许我们将(1)写为单行.
1)合并
m <- merge(df, table, all.x = TRUE) transform(m, label = ifelse(value < mean, "low", "high"), mean = NULL)
赠送:
item condition value label 1 1 control 10 low 2 2 control 11 high 3 3 control 12 high 4 1 related 20 low 5 2 related 21 high 6 3 related 22 high
1a)通过内连接,它可以缩短为:
transform(merge(df, table), label = ifelse(value < mean, "low", "high"), mean = NULL)
2)匹配
transform(df, label = ifelse(value < table$mean[match(condition, table$condition)], "low", "high") )
给予同样的.
3)sqldf
library(sqldf) sqldf("select df.*, case when value < mean then 'low' else 'high' end label from df left join 'table' using (condition)")
4)dplyr
library(dplyr) df %>% left_join(table) %>% mutate(label = ifelse(value < mean, "low", "high")) %>% select(- mean)
5)data.table
library(data.table) dt <- as.data.table(df) setkey(dt, "condition") dt[table, label := ifelse(value < mean, "low", "high")]