现实生活中的问题:我的受试者有MRI扫描数据。其中一些已被多次扫描(单独的行)。其中一些每次都在不同的协议下进行扫描。我希望按主题ID保留所有唯一的行,如果主题是在两种不同的协议下扫描的,我希望它优先于另一种。
玩具示例:
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!
我想通过id返回包含所有唯一主题的数据框。当涉及到重复值时,我希望它保留条目#34; Y&#34;而不是自动保留第一个条目。作为协议,如果它有这个选择,但不是摆脱与&#34; X&#34;除此以外。
在示例中,它将保留第2,3,4和6行。
我更喜欢dplyr,但我愿意接受其他建议。
我尝试过的任何事情都没有开始发挥作用:
df %>% arrange(id, desc(protocol == 'Y')) %>% distinct(id, .keep_all = TRUE)
两个好的答案: @RobJensen建议
df %>% group_by(id) %>% arrange(desc(protocol),var) %>% slice(1)
如果我有多个协议并希望分配一个它们将被选择的顺序,我可以创建一个新变量,我按优先顺序为协议分配一个整数,然后使用@joran中的建议
{{1}}
谢谢!
答案 0 :(得分:4)
按照字母顺序排列适用于所述的简单案例,但如果您愿意,可以添加protocol_preference
变量,以便在Y
不是&#39时对您选择的内容进行排序; t可用,并选择&#34; Y&#34;即使它不是按字母顺序排序的最后一个协议值。
建立@davechilders的答案和@Nathan Werth的想法,创建一个基于&#34;重要性顺序的因素&#34;矢量
order_of_importance <- c("Y", "Z", "X")
df2 %>%
mutate(protocol = factor(protocol, order_of_importance)) %>%
arrange(id, protocol) %>%
distinct(id, .keep_all = TRUE)
或者,如果您只是想选择&#39; Y&#39;并且如果&#39; Y&#39;并且没有选择所选的内容。你不能做任何事情
df %>%
arrange(id, desc(protocol == 'Y')) %>%
distinct(id, .keep_all = TRUE)
答案 1 :(得分:3)
这可能是一种更快的方式(几乎可以肯定是data.table),但这是 dplyr 中的天真直接方法我认为:
df %>% group_by(id) %>% arrange(desc(protocol),var) %>% do(head(.,1))
正如下面提到的@Gregor(现已删除),slice(1)
可能是do(head(.,1))
更好的习语。
答案 2 :(得分:1)
如果您希望输出为不是grouped_df的tibble,则可以在不使用group_by()
的情况下实现此目的。
df %>% arrange(id, desc(protocol)) %>% distinct(id, .keep_all = TRUE)
答案 3 :(得分:0)
你可以将这个过程分解为两个步骤:抓住必备品,抓住其他ID的任何内容,然后合并。
distinct_y <- df %>%
filter(protocol == "Y") %>%
distinct(id, .keep_all = TRUE)
distinct_other <- df %>%
anti_join(distinct_y, "id") %>%
distinct(id, .keep_all = TRUE)
distinct_combined <- rbind(distinct_y, distinct_other)
如果您想将其从“最重要的”推广到价值排序,我建议将protocol
作为一个因素。
例如,假设有三个协议:X,Y和Z.Y是最好的,Z优于X,如果没有更好的话,你只需要X.
# Only difference is the best protocol for C will now be Z.
df2 <- tibble(
id = c("A", "A", "B", "C", "C", "D"),
protocol = c("X", "Y", "X", "X", "Z", "Y"),
date = c(seq(as.Date("2018-01-01"), as.Date("2018-01-06"),
by="days")),
var = 1:6
)
order_of_importance <- c("Y", "Z", "X")
df2 %>%
mutate(protocol = factor(protocol, order_of_importance)) %>%
group_by(id) %>%
arrange(protocol) %>%
slice(1)
# # A tibble: 4 x 4
# # Groups: id [4]
# id protocol date var
# <chr> <fctr> <date> <int>
# 1 A Y 2018-01-02 2
# 2 B X 2018-01-03 3
# 3 C Z 2018-01-05 5
# 4 D Y 2018-01-06 6