根据分组的data.frame计算每对

时间:2019-03-15 13:07:36

标签: r dplyr

我的问题是关于在data.frame中的每对组之间执行计算,我希望它能被向量化。

我有一个data.frame,它由以下几列组成:LocationSampleVar1Var2。我想为SampleLocation的每一对Var1找到每个Var2的壁橱匹配。

我可以在一对位置上做到这一点,

df0 <- data.frame(Location = rep(c("A", "B", "C"), each =30), 
                 Sample = rep(c(1:30), times =3),
                 Var1 = sample(1:25, 90, replace =T),
                 Var2 = sample(1:25, 90, replace=T))
df00 <- data.frame(Location = rep(c("A", "B", "C"), each =30), 
                 Sample = rep(c(31:60), times =3),
                 Var1 = sample(1:100, 90, replace =T),
                 Var2 = sample(1:100, 90, replace=T))
df000 <- rbind(df0, df00)
df <- sample_n(df000, 100) # data

dfl <- df %>% gather(VAR, value, 3:4)

df1 <- dfl %>% filter(Location == "A")
df2 <- dfl %>% filter(Location == "B")
df3 <- merge(df1, df2, by = c("VAR"), all.x = TRUE, allow.cartesian=TRUE)
df3 <- df3 %>% mutate(DIFF = abs(value.x-value.y))
result <- df3 %>% group_by(VAR, Sample.x) %>% top_n(-1, DIFF)

我尝试了其他可能性,例如使用dplyr::spread,但无法避免出现“错误:行的重复标识符”或用NA填充一半的列。

对于每个可能的组对,是否有更干净,更自动化的方法?我想避免每对手工的子集和合并例程。

1 个答案:

答案 0 :(得分:1)

一种选择是使用“ combn”创建“位置”的成对组合,然后按照OP的代码进行其他步骤

 library(tidyverse)
 df %>% 
    # get the unique elements of Location
    distinct(Location) %>% 
    # pull the column as a vector
    pull %>% 
    # it is factor, so convert it to character
    as.character %>% 
    # get the pairwise combinations in a list
    combn(m = 2, simplify = FALSE) %>%
    # loop through the list with map and do the full_join
    # with the long format data df1
    map(~ full_join(df1 %>% 
                      filter(Location == first(.x)), 
                    df1 %>% 
                      filter(Location == last(.x)), by = "VAR") %>% 
             # create a column of absolute difference
             mutate(DIFF = abs(value.x - value.y)) %>%
             # grouped by VAR, Sample.x
             group_by(VAR, Sample.x) %>%
             # apply the top_n with wt as DIFF
             top_n(-1, DIFF))

此外,正如OP所提到的,有关自动接机而不是进行两次filter(不过不清楚预期的输出)

df %>% 
   distinct(Location) %>%
   pull %>%
   as.character %>% 
   combn(m = 2, simplify = FALSE) %>% 
   map(~ df1 %>% 
             # change here i.e. filter both the Locations
             filter(Location %in% .x) %>% 
             # spread it to wide format
             spread(Location, value, fill = 0) %>% 
             # create the DIFF column by taking the differene
             mutate(DIFF = abs(!! rlang::sym(first(.x)) - 
                              !! rlang::sym(last(.x)))) %>% 
             group_by(VAR, Sample) %>% 
             top_n(-1, DIFF))