有没有一种方法可以基于多个数据帧中的操作在R中创建新列?

时间:2020-03-30 17:23:23

标签: r dataframe dplyr

有人知道是否可以在一个数据框(在我的情况下为“部署”数据框)中使用变量在另一个数据框中创建变量吗?

例如,我有两个数据框:

df1:

   deploy <- data.frame(ID = c("20180101_HH1_1_1", "20180101_HH1_1_2", "20180101_HH1_1_3"), 
             Site_Depth = c(42, 93, 40), Num_Depth_Bins_Required = c(5, 100, 4), 
             Percent_Column_in_each_bin = c(20, 10, 25))

df2:

   sp.c <- data.frame(species = c("RR", "GS", "GT", "BR", "RS", "BA", "GS", "RS", "SH", "RR"), 
                      ct = c(25, 66, 1, 12, 30, 6, 1, 22, 500, 6), 
                      percent_dist_from_surf = c(11, 15, 33, 68, 71, 100, 2, 65, 5, 42))

我想在df2中创建新列,以分配每种种类并根据每个ID的Percent_Column_in_each_bin计数到一个bin中。例如,在20180101_HH1_1_3中,将有4个仓位,每个仓位占列的25%,而在该列的0-25%之内(在df2中)的所有物种都将位于仓位1中,而物种的25%至50%之内列将位于深度bin 2中,依此类推。我在想像的样子是:

    i.want.this <- data.frame(species = c("RR", "GS", "GT", "BR", "RS", "BA", "GS", "RS", "SH", "RR"), 
                      ct = c(25, 66, 1, 12, 30, 6, 1, 22, 500, 6), 
                      percent_dist_from_surf = c(11, 15, 33, 68, 71, 100, 2, 65, 5, 42),
                      '20180101_HH1_1_1_Bin' = c(1, 1, 2, 4, 4, 5, 1, 4, 1, 3),
                      '20180101_HH1_1_2_Bin' = c(2, 2, 4, 7, 8, 10, 1, 7, 1, 5), 
                      '20180101_HH1_1_3_Bin' = c(1, 1,  2, 3, 3, 4, 1, 3, 1, 2))

我对R很陌生,我不确定如何做到这一点。我需要为100多个ID(所有这些ID具有不同的深度,深度容器的数量以及每个容器中列的百分比)执行此操作,所以我希望我不需要手工完成所有操作。我曾尝试在dplyr中进行mutate,但无法从两个不同的数据帧中提取它。我也尝试过ifelse语句,但是我需要为每个ID分别运行ifelse语句。

我不知道我想做的事是否可行,但我感谢您的反馈。先感谢您!

编辑:我的最终目标是在每个ID的每个仓中找到每种物种的最大计数(max ct)。我一直在寻找这一点(使用@Ben的建议生成的垃圾箱)正在使用dplyr进行切片并找到这样的最大ID:

    20180101_HH1_1_1 <- sp.c %>%
                        group_by(20180101_HH1_1_1, species) %>%
                        arrange(desc(ct)) %>% 
                        slice(1) %>%
                        group_by(20180101_HH1_1_1) %>%
                        mutate(Count_Total_Per_Bin = sum(ct)) %>%
                        group_by(species, add=TRUE) %>% 
                        mutate(species_percent_of_total_in_bin = 
                             paste0((100*ct/Count_Total_Per_Bin) %>%
                        mutate(ID= "20180101_HH1_1_1 ") %>%
                        ungroup()

但是我必须为100个以上的ID执行此操作。我想要的输出将是这样的:

    end.goal <- data.frame(ID = c(rep("20180101_HH1_1_1", 8)),
                   species = c("RR", "GS", "SH", "GT", "RR", "BR", "RS", "BA"),
                   bin = c(1, 1, 1, 2, 3, 4, 4, 5),
                   Max_count_of_each_species_in_each_bin = c(11, 66, 500, 1, 6, 12, 30, 6),
                   percent_dist_from_surf = c(11, 15, 5, 33, 42, 68, 71, 100),
                   percent_each_species_max_in_each_bin = c((11/577)*100, (66/577)*100, (500/577)*100, 100, 100, (12/42)*100, (30/42)*100, 100))

我当时想通过回答原来的问题我可以解决这个问题,但是现在我看到您仍然需要做很多工作才能获得每个ID。

2 个答案:

答案 0 :(得分:0)

区分两个数据框的内容很有帮助。

  • df2似乎包含某些站点的测量值
  • df1似乎包含您要用来处理/汇总df2中的测量值的参数

鉴于两个数据框的这些不同目的,最好的方法可能是每次向df1添加一列时都遍历df2的所有行。类似于以下内容:

max_dist = max(df2$percent_dist_from_surf)

for(ii in 1:nrow(df1)){

  # extract parameters
  this_ID = df1[[ii,"ID"]]
  this_depth = df1[[ii,"Site_Depth"]]
  this_bins = df1[[ii,"Num_Depth_Bins_Required"]]
  this_percent = df1[[ii,"Percent_Column_in_each_bin"]]

  # add column to df2
  df2 = df2 %>%
    mutate(!!sym(this_ID) := insert_your_calculation_here)
}

代码的!!sym(this_ID) :=部分允许动态命名输出列。

最好,我可以确定您想要的insert_your_calculation_here公式为ceil(percent_dist_from_surf / max_dist * this_bins)

答案 1 :(得分:0)

这是另一种方法,不需要循环。

使用sapply可以cutpercent_dist_from_surf数据框中的每个deploy值确定bin。

res <- sapply(deploy$Percent_Column_in_each_bin, function(x) { 
  cut(sp.c$percent_dist_from_surf, seq(0, 100, by = x), include.lowest = TRUE, labels = 1:(100/x))
})
colnames(res) <- deploy$ID
cbind(sp.c, res)

或使用purrr

library(purrr)

cbind(sp.c, imap(setNames(deploy$Percent_Column_in_each_bin, deploy$ID), 
     ~ cut(sp.c$percent_dist_from_surf, seq(0, 100, by = .x), include.lowest = TRUE, labels = 1:(100/.x))
))

输出

   species  ct percent_dist_from_surf 20180101_HH1_1_1 20180101_HH1_1_2 20180101_HH1_1_3
1       RR  25                     11                1                2                1
2       GS  66                     15                1                2                1
3       GT   1                     33                2                4                2
4       BR  12                     68                4                7                3
5       RS  30                     71                4                8                3
6       BA   6                    100                5               10                4
7       GS   1                      2                1                1                1
8       RS  22                     65                4                7                3
9       SH 500                      5                1                1                1
10      RR   6                     42                3                5                2

修改

要确定每种物种,场所和垃圾箱的最大ct值,请将以上结果放入名为res的数据框中,然后执行以下操作。

第一个将以pivot_longer的形式出现。然后,您可以group_by种,场所和垃圾箱,并确定此组合的最大值ct

library(tidyverse)

res %>%
  pivot_longer(cols = starts_with("2018"), names_to = "site", values_to = "bin") %>%
  group_by(species, site, bin) %>%
  summarise(max_ct = max(ct)) %>%
  arrange(site, bin)

输出

# A tibble: 26 x 4
# Groups:   species, site [21]
   species site             bin   max_ct
   <fct>   <chr>            <fct>  <dbl>
 1 GS      20180101_HH1_1_1 1         66
 2 RR      20180101_HH1_1_1 1         25
 3 SH      20180101_HH1_1_1 1        500
 4 GT      20180101_HH1_1_1 2          1
 5 RR      20180101_HH1_1_1 3          6
 6 BR      20180101_HH1_1_1 4         12
 7 RS      20180101_HH1_1_1 4         30
 8 BA      20180101_HH1_1_1 5          6
 9 GS      20180101_HH1_1_2 1          1
10 SH      20180101_HH1_1_2 1        500
11 GS      20180101_HH1_1_2 2         66
12 RR      20180101_HH1_1_2 2         25
13 GT      20180101_HH1_1_2 4          1
14 RR      20180101_HH1_1_2 5          6
15 BR      20180101_HH1_1_2 7         12
16 RS      20180101_HH1_1_2 7         22
17 RS      20180101_HH1_1_2 8         30
18 BA      20180101_HH1_1_2 10         6
19 GS      20180101_HH1_1_3 1         66
20 RR      20180101_HH1_1_3 1         25
21 SH      20180101_HH1_1_3 1        500
22 GT      20180101_HH1_1_3 2          1
23 RR      20180101_HH1_1_3 2          6
24 BR      20180101_HH1_1_3 3         12
25 RS      20180101_HH1_1_3 3         30
26 BA      20180101_HH1_1_3 4          6