现实生活中的问题:我有核磁共振扫描数据。其中一些已被多次扫描(单独的行)。每一次都会根据不同的程序扫描其中一些。我希望按主题ID保留所有唯一的行,如果在两个不同的协议下扫描了一个主题,我希望它选择一个而不是另一个。
玩具例子:
library(dplyr)
df <- tibble(
id = c("A", "A", "B", "C", "C", "D"),
protocol = c("X", "Y", "X", "X", "X", "Y"),
date = c(seq(as.Date("2018-01-01"), as.Date("2018-01-06"),
by="days")),
var = 1:6)
我想返回一个数据框架与所有独特的主题通过id。当涉及一个重复值时,我希望它保留以"Y“作为协议的条目,如果它有这种选择的话,而不是自动保留第一个条目,但不保留带有"X”的行。
在本例中,它将保留第2、3、4和6行。
我更喜欢dplyr,但我愿意听取其他建议。
我尝试过的任何东西都没有开始起作用:
df %>% distinct(id, .keep_all = TRUE) #Nope!
df %>% distinct(id, protocol == "Y", .keep_all = TRUE) #Nope!
df$protocol <- factor(df$protocol, levels = c("Y", "X"))
df %>% distinct(id, .keep_all = TRUE) #Nope!
df %>% group_by(id) %>% filter(protocol == "Y") #Nope!
两个好答案:RobJensen建议
df %>% arrange(id, desc(protocol == 'Y')) %>% distinct(id, .keep_all = TRUE)
如果我有多个协议,并且希望指定一个选择它们的顺序,我可以创建一个新的变量,在这个变量中,我按照偏好顺序为协议分配一个整数,然后使用@joran的建议。
df %>% group_by(id) %>% arrange(desc(protocol),var) %>% slice(1)
谢谢!
发布于 2018-01-22 12:53:38
按字母顺序排列在所述的简单情况下是可行的,但如果您想要添加一个protocol_preference
变量,则可以按字母顺序排列您希望选择的内容,并选择"Y“,即使它不是按字母顺序排序时的最后一个协议值。
建立在@davechilders回答和@Nathan的想法的基础上建立一个基于“重要性顺序”向量的因素。
order_of_importance <- c("Y", "Z", "X")
df2 %>%
mutate(protocol = factor(protocol, order_of_importance)) %>%
arrange(id, protocol) %>%
distinct(id, .keep_all = TRUE)
或者,如果您只想选择'Y‘,而不喜欢所选的内容,如果'Y’是不可否认的,您可以这样做。
df %>%
arrange(id, desc(protocol == 'Y')) %>%
distinct(id, .keep_all = TRUE)
发布于 2018-01-22 12:33:28
如果您希望输出是一个不是group_by()
的tibble,则无需使用grouped_df就可以实现这一点。
df %>% arrange(id, desc(protocol)) %>% distinct(id, .keep_all = TRUE)
发布于 2018-01-22 12:29:11
可能有一种更快的方法(几乎可以肯定是使用data.table),但我认为,在dplyr中,这是一种天真的直接方法:
df %>% group_by(id) %>% arrange(desc(protocol),var) %>% do(head(.,1))
正如@Gregor (现在删除)所指出的,slice(1)
可能是do(head(.,1))
的一个更好的成语。
https://stackoverflow.com/questions/48389658
复制