【问题标题】:Calculation on every pair from grouped data.frame从分组的data.frame中计算每一对
【发布时间】:2019-03-15 13:07:35
【问题描述】:

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

我有一个包含以下列的 data.frame:LocationSampleVar1Var2。我想为Var1Var2 的每对Locations 找到每个Sample 的壁橱匹配项。

我可以为一对这样的位置完成此操作:

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 的列。

对于每个可能的组对,是否有更简洁和自动化的方法来执行此操作?我想避免每对的手动子集和合并例程。

【问题讨论】:

    标签: r dplyr


    【解决方案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))
    

    【讨论】:

    • 第一个解决方案会产生所需的结果。在管道程序中进行双重过滤是很好的。
    • @nofunsally 谢谢,第二个我不清楚。在第一个中,有一个 full_join,它可以在第二个中复制
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-11
    • 2013-09-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-14
    相关资源
    最近更新 更多