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 = '_')