R 重复行:根据条件选择行并存储重复的值
我正在处理的原始数据集如下所示:R 重复行:根据条件选择行并存储重复的值,r,duplicates,R,Duplicates,我正在处理的原始数据集如下所示: df <- data.frame("ID" = c("Alpha", "Alpha", "Alpha", "Alpha", "Beta","Beta", "Beta","Beta" ), "treatment"= LETTERS[seq(from = 1, to = 8)], "Year" = c(1970, 1970, 1980, 1
df <- data.frame("ID" = c("Alpha", "Alpha", "Alpha", "Alpha",
"Beta","Beta", "Beta","Beta" ),
"treatment"= LETTERS[seq(from = 1, to = 8)],
"Year" = c(1970, 1970, 1980, 1990, 1970, 1980,
1980,1990),
"Val" = c(0,0,0,1,0,1,0,1),
"Val2" = c(0,2.34,1.3,0,0,2.34,3.2,1.3))
逻辑如下:
1) 我希望每个ID/年只有一个obs
2) 我只想在Val2
类别中保留具有较高值的观察值
3) 我想将删除的行值存储到单独的列中,以跟踪我正在删除的内容del_treat
、del_Val
和del_Val2
举例说明。在df中,对Alpha/1970进行了重复观测。我想把这减少到一行。Val2的值为0和2.34,在最终数据帧中,仅保留2.34。但是,治疗A的值在新创建的列del_treat
、del_Val
和del_Val2
中报告
我可以根据Val2``setDT(df)[order(-Val2)][,.SD[1,],by=(ID,Year)]
值,但我想找到一种简洁的方法将删除的结果“存储”到新列中这里有一个使用
dplyr
的选项。按“ID”、“Year”分组后,创建一个逻辑列(“ind”),检查“Val2”的max
,使用该逻辑列创建与“Val”相对应的两列,并将“del”作为前缀用于已消除的值,以及不存在的“treatment”,根据“ind”和取消分组
library(dplyr)
df %>%
group_by(ID, Year) %>%
mutate(ind = Val2 == max(Val2) & !is.na(Val2)) %>%
mutate_at(vars(matches('Val')),
list(del = ~ if(any(!ind)) .[!ind] else NA_real_)) %>%
mutate(del_treat = if(any(!ind)) treatment[!ind] else NA_character_) %>%
filter(ind) %>%
ungroup %>%
select(-ind)
这里有一个带有dplyr
的选项。按“ID”、“Year”分组后,创建一个逻辑列(“ind”),检查“Val2”的max
,使用该逻辑列创建与“Val”相对应的两列,并将“del”作为前缀用于已消除的值,以及不存在的“treatment”,根据“ind”和取消分组
library(dplyr)
df %>%
group_by(ID, Year) %>%
mutate(ind = Val2 == max(Val2) & !is.na(Val2)) %>%
mutate_at(vars(matches('Val')),
list(del = ~ if(any(!ind)) .[!ind] else NA_real_)) %>%
mutate(del_treat = if(any(!ind)) treatment[!ind] else NA_character_) %>%
filter(ind) %>%
ungroup %>%
select(-ind)
使用data.table,在按Val2
降序排序后,基于rowid(ID,Year)
的dcast可以实现除列名之外的其他目的。“_1”列是“keep”列,“_2”列是“del”列
库(data.table)
setDT(df)
setorder(df,ID,年份,-Val2)
每组输出2行
setnames(out, function(x) gsub('(.*)_1', '\\1', x))
setnames(out, function(x) gsub('(.*_\\d+)', 'del_\\1', x))
out
# ID Year treatment del_treatment_2 Val del_Val_2 Val2 del_Val2_2
# 1: Alpha 1970 B A 0 0 2.34 0.00
# 2: Alpha 1980 C <NA> 0 NA 1.30 NA
# 3: Alpha 1990 D <NA> 1 NA 0.00 NA
# 4: Beta 1970 E <NA> 0 NA 0.00 NA
# 5: Beta 1980 G F 0 1 3.20 2.34
# 6: Beta 1990 H <NA> 1 NA 1.30 NA
setnames(out,函数(x)gsub('(.*)1','\\1',x))
集合名(out,函数(x)gsub(“(.*\\d+”,“del\\1',x))
出来
#ID年治疗日期日期日期日期日期日期日期日期日期日期日期日期日期日期日期日期日期日期日期日期日期日期日期日期日期日期日期日期日期日期日期日期日期日期日期日期日期日期日期日期日期日期日期日期日期日期日期日期日期日期日期日期日期日期日期日期日期日期日期日期日期日期日期日期日期日期日期
#1:Alpha 1970 B 0 0 2.34 0.00
#2:Alpha 1980 C0 NA 1.30 NA
#3:Alpha 1990 D 1 NA 0.00 NA
#4:Beta 1970 E 0 NA 0.00 NA
#5:Beta 1980 G F 0 1 3.20 2.34
#6:Beta 1990 H1 NA 1.30 NA
使用data.table,在按Val2
降序后,基于rowid(ID,Year)
的dcast可以实现除列名之外的其他功能。“_1”列是“keep”列,“_2”列是“del”列
库(data.table)
setDT(df)
setorder(df,ID,年份,-Val2)
每组输出2行
setnames(out, function(x) gsub('(.*)_1', '\\1', x))
setnames(out, function(x) gsub('(.*_\\d+)', 'del_\\1', x))
out
# ID Year treatment del_treatment_2 Val del_Val_2 Val2 del_Val2_2
# 1: Alpha 1970 B A 0 0 2.34 0.00
# 2: Alpha 1980 C <NA> 0 NA 1.30 NA
# 3: Alpha 1990 D <NA> 1 NA 0.00 NA
# 4: Beta 1970 E <NA> 0 NA 0.00 NA
# 5: Beta 1980 G F 0 1 3.20 2.34
# 6: Beta 1990 H <NA> 1 NA 1.30 NA
setnames(out,函数(x)gsub('(.*)1','\\1',x))
集合名(out,函数(x)gsub(“(.*\\d+”,“del\\1',x))
出来
#ID年治疗日期日期日期日期日期日期日期日期日期日期日期日期日期日期日期日期日期日期日期日期日期日期日期日期日期日期日期日期日期日期日期日期日期日期日期日期日期日期日期日期日期日期日期日期日期日期日期日期日期日期日期日期日期日期日期日期日期日期日期日期日期日期日期日期日期日期日期
#1:Alpha 1970 B 0 0 2.34 0.00
#2:Alpha 1980 C0 NA 1.30 NA
#3:Alpha 1990 D 1 NA 0.00 NA
#4:Beta 1970 E 0 NA 0.00 NA
#5:Beta 1980 G F 0 1 3.20 2.34
#6:Beta 1990 H1 NA 1.30 NA
非常感谢,这非常高效!非常感谢,这是非常有效的!