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



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

例如,我有两个数据帧:

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将每个物种和计数分配给一个仓。例如,在20180101_HH1_1_3中,将有4个仓,每个仓占该列的25%,位于该列(在df2(0-25%范围内的所有物种都将位于仓1中,位于该柱25-50%范围内的物种将位于深度仓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中进行变异,但我无法从两个不同的数据帧中提取它。我也尝试过ifelse语句,但我需要分别为每个ID运行ifelse声明。

我不知道我想做的事情是否可行,但我很感激反馈。提前谢谢!

编辑:我的最终目标是找到每个ID的每个箱子中每个物种的最大计数(最大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多个身份证做这件事。我想要的输出是:

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,你还需要做很多事情。

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

使用sapply,您可以cutdeploy数据帧中的每个percent_dist_from_surf值确定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物种、站点和bin,并确定该组合的最大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

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

  • df2似乎包含一些站点的测量值
  • df1似乎包含一些参数,您希望通过这些参数来处理/总结df2中的测量结果

考虑到这两个数据帧的这些不同用途,您最好的方法可能是每次向df2添加一列时,在df1的所有行上循环。类似以下内容:

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)

最新更新