For循环:计算两个数据帧之间的匹配项和唯一元素,并将函数应用于计数
我想进行一个非常复杂的循环。我有多个区域,每个区域在我的真实数据框中有数百个图。我想按区域划分子集,然后在子集上绘制和执行各种函数,以最终计算只有共享物种的差异性。我将在前言中说,每一行都代表着一种互动 我的示例For循环:计算两个数据帧之间的匹配项和唯一元素,并将函数应用于计数,r,for-loop,R,For Loop,我想进行一个非常复杂的循环。我有多个区域,每个区域在我的真实数据框中有数百个图。我想按区域划分子集,然后在子集上绘制和执行各种函数,以最终计算只有共享物种的差异性。我将在前言中说,每一行都代表着一种互动 我的示例df: set.seed(540) df<- data.frame(region= c(rep(1, 16), rep(2,8)), plot= c(rep("A",5), rep("B",9), rep("C", 2), rep("D", 6),re
df
:
set.seed(540)
df<- data.frame(region= c(rep(1, 16), rep(2,8)),
plot= c(rep("A",5), rep("B",9), rep("C", 2), rep("D", 6),rep("E", 2)),
plantsp= sample(1:24,24, replace= TRUE),
lepsp= sample(1:24,24,replace= TRUE),
psitsp= sample(1:24,24,replace= TRUE))
df[] <- lapply(df, as.character)
df$plantsp<-paste('plantsp', df$plantsp, sep='_')
df$lepsp<-paste('lepsp', df$lepsp, sep='_')
df$psitsp<-paste('psitsp', df$psitsp, sep='_')
df$paste1<- paste(df$plantsp, df$lepsp, sep='_')
df$paste2<- paste(df$lepsp, df$psitsp, sep='_')
df$paste3<- paste(df$plantsp,df$lepsp, df$psitsp)
请注意,仅保留那些具有共享种类的行。此外,只有那些具有同样相互作用的共享物种的行仍然存在。此外,我还删除了不必要的列(例如,psitsp
,paste2
,paste3
),以提请您注意此步骤的结果。代码不需要删除这些列
步骤4:对lepsp
和psitsp
列重复步骤3,以生成dfu sub2
。例如:
region_sub <- split(df, df$region)
plot_sub <- split(region_sub[[1]], region_sub[[1]][[2]])
df_sub2<- df[1:5,c(1:2,4,5,7)]
df_sub3<- df[1:5,c(1:5,8)]
sum_match<- 15
sum_unique<- 1
步骤6:现在所有子集都已生成,我想计算plot_sub1
和df_sub1
中pase1
列中的匹配元素(=5)。例子:
这将存储在向量匹配中。结果将相应地存储在匹配或唯一向量中。例如:
match<- length(intersect(df_sub1$paste1, plot_sub[[1]]$paste1))
match
注:如果df\u sub
具有重复交互或匹配,则plot\u sub
之间的匹配只需计算1次。这需要解释比赛的存在——比赛的缺乏,而不是比赛的丰富
总之,对于该子集,两个向量为:
match<- c( length(intersect(df_sub1$paste1, plot_sub[[1]]$paste1)),
length(intersect(df_sub2$paste2, plot_sub[[1]]$paste2)),
length(intersect(df_sub3$paste3, plot_sub[[1]]$paste3))
match
unique<-c(1,0,0)
我真的很感激任何时候有人愿意帮助我实现循环中的论点。这对我来说是个棘手的问题。谢谢你在评论中所做的所有澄清
下面是我使用tidyverse
的解决方案
代码+解释
## Load packages
library(tidyverse)
## Nest data
new_df <- df %>%
group_by(region, plot) %>%
nest(.key = plot_sub)
new_df
# A tibble: 5 x 3
# region plot plot_sub
# <dbl> <fctr> <list>
# 1 1 A <tibble [5 x 3]>
# 2 1 B <tibble [9 x 3]>
# 3 1 C <tibble [2 x 3]>
# 4 2 D <tibble [6 x 3]>
# 5 2 E <tibble [2 x 3]>
现在,我定义了要创建df_sub
的列,然后将该函数应用于plot_sub
-列
col_list1 <- c('plantsp', 'lepsp')
col_list2 <- c('lepsp', 'psitsp')
col_list3 <- c('plantsp', 'lepsp', 'psitsp')
new_df <- new_df %>%
mutate(df_sub1 = map(plot_sub, create_df_sub, df = df, col_list = col_list1),
df_sub2 = map(plot_sub, create_df_sub, df = df, col_list = col_list2),
df_sub3 = map(plot_sub, create_df_sub, df = df, col_list = col_list3))
新的交互添加到df_sub1
中
为了提取匹配值和唯一值,我在plot\u sub
列和不同的df\u sub
上使用internal\u join
和anti\u join
new_df <- new_df %>%
mutate(match1 = map2(df_sub1, plot_sub, inner_join, by = col_list1),
match2 = map2(df_sub2, plot_sub, inner_join, by = col_list2),
match3 = map2(df_sub3, plot_sub, inner_join, by = col_list3),
unique1 = map2(df_sub1, plot_sub, anti_join, by = col_list1),
unique2 = map2(df_sub2, plot_sub, anti_join, by = col_list2),
unique3 = map2(df_sub3, plot_sub, anti_join, by = col_list3))
在最后一步中,我提取每个匹配
和唯一
的行数,并将其相加。我还计算了res\u vec
new_df <- new_df %>%
mutate(sum_match = map_int(match1, nrow) + map_int(match2, nrow) + map_int(match3, nrow),
sum_unique = map_int(unique1, nrow) + map_int(unique2, nrow) + map_int(unique3, nrow),
res_vec = ((sum_match + sum_unique)/((2*sum_match + sum_unique)/2)) - 1)
数据
set.seed(540)
df <- data.frame(region = c(rep(1, 16), rep(2, 8)),
plot = c(rep('A', 5), rep('B', 9), rep('C', 2), rep('D', 6),rep('E', 2)),
plantsp = sample(1:24, 24, replace = TRUE),
lepsp = sample(1:24, 24, replace = TRUE),
psitsp = sample(1:24, 24, replace = TRUE))
df$plantsp <- paste('plantsp', df$plantsp, sep = '_')
df$lepsp <- paste('lepsp', df$lepsp, sep = '_')
df$psitsp <- paste('psitsp', df$psitsp, sep = '_')
set.seed(540)
df我很欣赏这个可复制的例子,但我对df_sub1
的逻辑感到困惑。在您的示例中,您说df_sub1
应该包括df
的第22行,其中包含plantsp_9
和“lepsp_2”。但是,plot_sub1
中没有一行同时具有这两个值。因此,我不明白为什么df[22,]
包含在df_sub1
中。此外,df[16,]
有plantsp_21
和lepsp_19
,它们与plot_sub1[2,]
完全匹配,因此我也不明白为什么df[16,]
没有包含在df_sub1
中。也许它与“删除具有任何唯一条目的行”有关,在本文中,我也不理解这一点,因为df[c(1,2,3,4,5,22),c(1:4,6)]
的所有行都是唯一的,并且在plantsp
列中只有plantsp_9
重复,其他四个值在dfu sub1
中是唯一的,我感谢您的提问,而不是放弃我的问题!你的问题很好,为什么我的分析(在我看来)很酷。回答您的第一个问题:在df_sub1
的第22行,虽然plantsp9和lepsp2在plot_sub1
中没有交互作用,但它们都在该图中。所以我想知道,在它们共有的物种子集中,有什么不同的相互作用。通过包含ROW22,我计算了不同的交互物种,我需要对这些实例进行计数。在我的例子中,我不考虑<代码> df(16,)< />代码,因为这是情节C的一部分,这是循环的第三次迭代的一部分。我需要为每个绘图子集分别重复步骤3-7(例如,在循环的下一次迭代中将是plot_sub2
及其相应的df_sub1
,df_sub2
,df_sub3
,第三次迭代是plot_sub3
及其相应的df_sub1
,df_sub2
,df_sub3
,等等。)好的,我想我对df row的理解更好22-它被包括在dfu sub1
中,因为它的plantsp
和lepsp
值都出现在plot\u sub1
中的某个地方,即使它们不在同一行中。正确吗?哇。我非常感谢,印象深刻。这非常有效。唯一的小修正是res\u vec
公式。它没有计算回答正确。res_-vec
应该是res_-vec我还没有在我的真实数据上运行它。你知道这种方法或循环会更快吗?这将是一个巨大的数据集(即超过9个区域和1500个绘图)我很好奇,与循环相比,您的解决方案运行的速度有多快。我想这比循环快,但您可以使用microbenchmark
首先比较不同的方法,然后选择最快的方法。这是一个很好的解决方案,感谢microbenchmark
的建议,我没有意识到这一点,这会有所帮助很多。我已经更新了我的OP来解释我的错误,所以我建议你更新你的答案。谢谢你花了这么多时间在这上面。非常好!我很高兴还没有得到一个答案-很高兴你得到了!
col_list1 <- c('plantsp', 'lepsp')
col_list2 <- c('lepsp', 'psitsp')
col_list3 <- c('plantsp', 'lepsp', 'psitsp')
new_df <- new_df %>%
mutate(df_sub1 = map(plot_sub, create_df_sub, df = df, col_list = col_list1),
df_sub2 = map(plot_sub, create_df_sub, df = df, col_list = col_list2),
df_sub3 = map(plot_sub, create_df_sub, df = df, col_list = col_list3))
new_df$plot_sub[[1]]
# A tibble: 5 x 3
# plantsp lepsp psitsp
# <chr> <chr> <chr>
# 1 plantsp_2 lepsp_19 psitsp_19
# 2 plantsp_21 lepsp_19 psitsp_4
# 3 plantsp_19 lepsp_2 psitsp_11
# 4 plantsp_9 lepsp_13 psitsp_24
# 5 plantsp_24 lepsp_9 psitsp_2
new_df$df_sub1[[1]]
# A tibble: 6 x 3
# plantsp lepsp paste_col
# <chr> <chr> <chr>
# 1 plantsp_2 lepsp_19 plantsp_2_lepsp_19
# 2 plantsp_21 lepsp_19 plantsp_21_lepsp_19
# 3 plantsp_19 lepsp_2 plantsp_19_lepsp_2
# 4 plantsp_9 lepsp_13 plantsp_9_lepsp_13
# 5 plantsp_24 lepsp_9 plantsp_24_lepsp_9
# 6 plantsp_9 lepsp_2 plantsp_9_lepsp_2
new_df <- new_df %>%
mutate(match1 = map2(df_sub1, plot_sub, inner_join, by = col_list1),
match2 = map2(df_sub2, plot_sub, inner_join, by = col_list2),
match3 = map2(df_sub3, plot_sub, inner_join, by = col_list3),
unique1 = map2(df_sub1, plot_sub, anti_join, by = col_list1),
unique2 = map2(df_sub2, plot_sub, anti_join, by = col_list2),
unique3 = map2(df_sub3, plot_sub, anti_join, by = col_list3))
new_df$match1[[1]]
# A tibble: 5 x 4
# plantsp lepsp psitsp paste_col
# <chr> <chr> <chr> <chr>
# 1 plantsp_2 lepsp_19 psitsp_19 plantsp_2_lepsp_19
# 2 plantsp_21 lepsp_19 psitsp_4 plantsp_21_lepsp_19
# 3 plantsp_19 lepsp_2 psitsp_11 plantsp_19_lepsp_2
# 4 plantsp_9 lepsp_13 psitsp_24 plantsp_9_lepsp_13
# 5 plantsp_24 lepsp_9 psitsp_2 plantsp_24_lepsp_9
new_df$unique1[[1]]
# A tibble: 1 x 3
# plantsp lepsp paste_col
# <chr> <chr> <chr>
# 1 plantsp_9 lepsp_2 plantsp_9_lepsp_2
new_df <- new_df %>%
mutate(sum_match = map_int(match1, nrow) + map_int(match2, nrow) + map_int(match3, nrow),
sum_unique = map_int(unique1, nrow) + map_int(unique2, nrow) + map_int(unique3, nrow),
res_vec = ((sum_match + sum_unique)/((2*sum_match + sum_unique)/2)) - 1)
new_df %>% select(region, plot, sum_match, sum_unique, res_vec)
# A tibble: 5 x 5
# region plot sum_match sum_unique res_vec
# <dbl> <fctr> <int> <int> <dbl>
# 1 1 A 15 1 0.03225806
# 2 1 B 27 3 0.05263158
# 3 1 C 6 2 0.14285714
# 4 2 D 18 1 0.02702703
# 5 2 E 6 0 0.00000000
set.seed(540)
df <- data.frame(region = c(rep(1, 16), rep(2, 8)),
plot = c(rep('A', 5), rep('B', 9), rep('C', 2), rep('D', 6),rep('E', 2)),
plantsp = sample(1:24, 24, replace = TRUE),
lepsp = sample(1:24, 24, replace = TRUE),
psitsp = sample(1:24, 24, replace = TRUE))
df$plantsp <- paste('plantsp', df$plantsp, sep = '_')
df$lepsp <- paste('lepsp', df$lepsp, sep = '_')
df$psitsp <- paste('psitsp', df$psitsp, sep = '_')