【问题标题】:R replace nested for loops with dplyr when column lookup is from a different data.frame当列查找来自不同的data.frame时,R用dplyr替换嵌套的for循环
【发布时间】:2020-07-31 21:21:09
【问题描述】:

当 group_by 信息来自与汇总单元不同的 data.frame 时,此问题的核心涉及使用 dplyr。 例子: 我已将位置分配给其他地方的组。 将一组位置分配给组的每个唯一分配都是一个计划。 有成千上万的计划。我正在寻找有关每个计划的汇总统计信息。

我在一个缓慢的嵌套 for 循环中执行此操作,并希望尽可能加快该过程。我希望我可以使用 group_by 和 summarise 来做到这一点,但是语法使我难以理解,我发现的示例都具有来自同一个 tibble 或 data.frame 的查找。 可复制的例子:

# locations (x,y), populations at those locations (popA, popB)   
df <- data.frame(x = rep(1:3, times = 3),
                 y = c(1,1,1,2,2,2,3,3,3),
                 popA = c(1,2,3,4,5,6,7,8,9),
                 popB = c(10,11,12,13,14,15,16,17,18))

# plans (Runs 1 through 3) each plan is a column in the data.frame and the
# value indicates the group to which each location was assigned in that plan  
result < -data.frame(Run1 = c(1,1,1,2,2,2,3,3,3),
                     Run2 = c(1,2,3,1,2,3,1,2,3),
                     Run3 = c(1,1,3,2,2,3,3,3,3))

#The data.frame where I will store my summary statistics.    
#Plan | District | Pop A | Pop B | Total
pop.by.dist <- data.frame(Plan = rep(NA,(max(result$Run1))*length(colnames(result))),
                          District = NA, PopA = NA, PopB = NA, Total = NA)

counter = 1
for(i in 1:length(colnames(result))){ #for every plan
  for(j in 1:max(result)){ #for every district
    tmp <- colSums(df[result[,i]==j,c("popA","popB")])
    pop.by.dist[counter,] <- c(colnames(result)[i],j,tmp,sum(tmp))
    counter <- counter+1
  }
}
pop.by.dist #output has one row per plan * district combination

    #> pop.by.dist
    #  Plan District PopA PopB Total
    #1 Run1        1    6   33    39
    #2 Run1        2   15   42    57
    #3 Run1        3   24   51    75
    #4 Run2        1   12   39    51
    #5 Run2        2   15   42    57
    #6 Run2        3   18   45    63
    #7 Run3        1    3   21    24
    #8 Run3        2    9   27    36
    #9 Run3        3   33   78   111

我知道这里已经有大量相关问题,但是我很难找到从另一个 data.frame 进行查找的具体需求。我不是新用户,并且已经花了一些时间寻找可以开始工作的回复,所以在您将我标记为重复之前,请包含解决我的问题的代码。你可能只是帮助下一个人。

【问题讨论】:

    标签: r dplyr


    【解决方案1】:

    如果只绑定两个数据框没有问题,先这样:

    new_df <- cbind(df, result)
    

    然后你把你的数据变成长格式,然后分组,然后总结:

    new_df %>% pivot_longer(c(Run1, Run2, Run3), 
                            names_to = "Plan", 
                            values_to = "District") %>% 
      group_by(Plan, District) %>% 
      summarise_at(vars(popA, popB), sum) %>%
      mutate(Total = popA + popB)
    
    # A tibble: 9 x 5
    # Groups:   Plan [3]
      Plan  District  popA  popB Total
      <chr>    <dbl> <dbl> <dbl> <dbl>
    1 Run1         1     6    33    39
    2 Run1         2    15    42    57
    3 Run1         3    24    51    75
    4 Run2         1    12    39    51
    5 Run2         2    15    42    57
    6 Run2         3    18    45    63
    7 Run3         1     3    21    24
    8 Run3         2     9    27    36
    9 Run3         3    33    78   111
    

    【讨论】:

    • 刚刚在开始时投入了 df %>% cbind(result)%>% 并删除了 new_df 并且它可以工作。我是如此接近但错过了pivot_longer。谢谢!
    猜你喜欢
    • 2021-08-09
    • 1970-01-01
    • 1970-01-01
    • 2020-06-03
    • 2018-05-21
    • 2019-06-06
    • 1970-01-01
    • 2020-10-06
    • 1970-01-01
    相关资源
    最近更新 更多