我正在尝试使用dplyr对一些小数据(数据帧)进行数据整理,以消除重复记录,如果id出现两次,则结果记录将包含相同的值(如果它们都相同),或者包含NA其中一条记录存在差异。例如,如果我有df:
id date amount tag
--- ---- ------ ---
1 2018-01-03 10 big
2 2019-01-16 20 small
3 2020-01-05 30 big
3 2001-03-04 30 big
1 2018-01-03 5 big
结果应如下所示:
id date amount tag
--- ---- ------ ---
1 2018-01-03 NA big
2 2019-01-16 20 small
3 NA 30 big
基于我在堆栈溢出时发现的其他答案,我尝试了各种使用summarise_all的方法,包括:
new_df <- df %>% group_by(id) %>% summarise_all(function(x) ifelse(all(x[1] == x),x[1],NA))
new_df <- df %>% group_by(id) %>% summarise_all(list(~ if(all(.[1] == .)) .[1] else NA))
new_df <- df %>% group_by(id) %>% summarise_all(funs(if(all(.[1] == .)) .[1] else NA))
由于我可以自己将ifelse(all(x[1] == x),x[1],NA)
与向量一起使用,并且效果很好,所以我认为可以与summarise_all一起使用。但是,当我将其与summarise_all
或上面显示的其他变体一起使用时,会出现错误:
Error in summarise_impl(.data, dots): Column `date` can't promote group 2 to character
我怀疑我只需要对代码进行一些细微调整就可以使其正常工作,但是我整天都在工作,我不知道为什么它不工作...所以任何社区提供的帮助将不胜感激。这是我第一次真正问到堆栈溢出问题,因为我几乎总是可以从其他人的问题中找到答案:-)非常感谢您的帮助!
答案 0 :(得分:2)
首先,解决方案:
d %>%
group_by(id) %>%
summarise_all(~if(n_distinct(.) == 1) first(.) else c(NA, .)[1])
这实际上有点棘手。您可能会想简单地写:
d %>%
group_by(id) %>%
summarise_all(~if(n_distinct(.) == 1) first(.) else NA)
这只是if (all ...) ... else ...
的替代方法,它使用了更多的dplyr
函数。
但是,dplyr
不喜欢简单地给NA
,而是需要特定于类型。例如。您需要提供NA_character_
或NA_integer_
等以匹配正确的数据类型。这就是您的代码失败的原因,该错误表明第2组(在这种情况下为id == 2
)没有被“提升”为字符。这意味着NA
列中提供的Date
不会被强制转换为字符,并且无法创建新列。
由于您不想编写所有正确的NA
类型的代码,因此我在这里使用了一些技巧。使用c(NA, .)[1]
将NA
的值与原始变量组合在一起会将NA
强制转换为正确的类型,然后使用该类型。您可能还可以使用其他技巧来获取正确的NA
。