R:如何根据另一个变量中的值选择dplyr :: distinct()保留哪一行?

Bar*_*art 8 r unique distinct-values dplyr

现实生活中的问题:我有MRI扫描数据的科目.其中一些已被多次扫描(单独的行).其中一些每次都在不同的协议下进行扫描.我希望按主题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)
Run Code Online (Sandbox Code Playgroud)

我想通过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!
Run Code Online (Sandbox Code Playgroud)

两个好的答案:@RobJensen建议

df %>% arrange(id, desc(protocol == 'Y')) %>% distinct(id, .keep_all = TRUE)  
Run Code Online (Sandbox Code Playgroud)

如果我有多个协议并希望分配一个它们将被选择的顺序,我可以创建一个新变量,我按优先顺序为协议分配一个整数,然后使用@joran中的建议

df %>% group_by(id) %>% arrange(desc(protocol),var) %>% slice(1)  
Run Code Online (Sandbox Code Playgroud)

谢谢!

Ice*_*can 8

在所述的简单情况下按字母顺序排列是可行的,但是如果您愿意,您可以添加一个protocol_preference变量来对您希望选择的内容进行排序(如果Y不可用),并选择“Y”,即使它没有发生按字母顺序排序时成为最后一个协议值。

建立在@davechilders 答案和@Nathan Werth 基于“重要性顺序”向量创建因子的想法

order_of_importance <- c("Y", "Z", "X")

    df2 %>%
      mutate(protocol = factor(protocol, order_of_importance)) %>%
      arrange(id, protocol) %>%
      distinct(id, .keep_all = TRUE)
Run Code Online (Sandbox Code Playgroud)

或者,如果您只想选择“Y”并且如果“Y”不可用,则对所选内容没有偏好,您可以这样做

df %>% 
    arrange(id, desc(protocol == 'Y')) %>% 
    distinct(id, .keep_all = TRUE)
Run Code Online (Sandbox Code Playgroud)


dav*_*ers 5

group_by()如果您希望输出是不是 grouped_df 的 tibble,则可以在不使用的情况下实现此目的。

df %>% arrange(id, desc(protocol)) %>% distinct(id, .keep_all = TRUE)
Run Code Online (Sandbox Code Playgroud)