我想进行一个非常复杂的循环。我有多个区域,每个区域在我的实际数据框中有数百个图。我想按区域进行子集化,然后在子集上绘制和预先形成各种函数,以最终计算欠共享物种的不相似性。我将在序言中说每一行代表一种互动。
我的示例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)
步骤1:按区域子集df。例如:
region_sub <- split(df, df$region)
步骤2:按图绘制子集df。例如:
plot_sub <- split(region_sub[[1]], region_sub[[1]][[2]])
步骤3:我们将从绘图子集上方的步骤调用每个子集(每个列表组件)。在这个例子中,我将使用第一个子集(region1,plotA)作为所有后续输出的示例。我将调用此region1,plotA subset plot_sub1
。我想将plot_sub1
与原始df
进行比较,以生成三个df
子集。我们会将这些df_sub1
,df_sub2
,df_sub3
称为。首先,df_sub1
由plantsp
和lepsp
中plot_sub1
,df
列中的条目之间的匹配组成。将删除包含任何唯一条目的行,以及plantsp
匹配但不匹配lepsp
的行,反之亦然。 df_sub1
的示例:
df_sub1<- df[c(1,2,3,4,5,22),c(1:4,6)]
请注意,只有具有共享物种的行仍然存在。此外,只有具有共同物种的那些行也会保持相互作用。此外,我删除了不必要的列(例如psitsp
,paste2
,paste3
),以引起您对此步骤结果的注意。不需要为代码删除这些列。
步骤4:对lepsp
和psitsp
列重复步骤3以生成df_sub2
。例如:
df_sub2<- df[1:5,c(1:2,4,5,7)]
步骤5:对plantsp
,lepsp
和psitsp
列重复步骤3以生成df_sub3
。例如:
df_sub3<- df[1:5,c(1:5,8)]
步骤6:既然已经制作了所有子集,我想计算paste1
和plot_sub1
(= 5)中df_sub1
列中的匹配元素。例:
这将存储在向量match
中。结果将相应地存储在匹配或唯一向量中。示例:
match<- length(intersect(df_sub1$paste1, plot_sub[[1]]$paste1))
match
我还想计算独特的元素(= 1)。这将存储在向量unique
中。对于plot_sub1
和df_sub2
以及plot_sub1
和df_sub3
,将重复此操作。我不知道如何计算两个df中的唯一元素,所以我不能提供示例代码。
unique<- 1
注意:plot_sub
中的匹配只需要在df_sub
重复交互或匹配的情况下计算一次。这需要考虑是否存在匹配,而不是丰度。
总结这个子集,两个向量将是:
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)
然后将为每个向量合计总和。例如:
sum_match<- 15
sum_unique<- 1
Step7:最后,这些值将输入到函数中:
((a + b)/((2 * a + b)/ 2) - 1)其中a = sum_match
且b = sum_unique
。
然后将该值输入结果向量res_vec
。
步骤8:对每个绘图子集迭代此过程(步骤3-7)。
实际上,这将计算绘图交互和相应的metaweb(所有可能的交互)之间共享交互的不相似性。这是(Poisot等人2012)对三重营养相互作用的修改。
这很可悲,但是为了启动for循环,我有:
res_vec<- NA
for (i in 1:length(unique(df$region)))
{
for (j in 1:length(unique(df$plot)))
{
我非常感谢任何人愿意帮助我实现循环中的论点。这就是让我变得棘手的地方。
答案 0 :(得分:1)
Thans @Gregor,你已经在评论中做了所有澄清!
以下是我使用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]>
列plot_sub
包含与您问题中具有相同名称的列表相同的数据。将此列视为数据框列表。
我知道写一个函数来创建df_sub
&#39。这使我们的代码更加干净,并避免不必要的重复。然后,此功能将应用于我们的专栏plot_sub
# Function to create the df_sub
# Takes the plot_sub, original dataframe (df) and a list of columns, which should be compared
# Returns the desired df_sub with new interactions of species which are in plot_sub
# Only unique interactions are returned
create_df_sub <- function(plot_sub, df, col_list){
# Filter df such that it only contains species which are in plot_sub
for (x in col_list) {
df <- df[df[[x]] %in% plot_sub[[x]], ]
}
# Combine plot_sub and filtered df
df_sub <- rbind(plot_sub[, col_list], df[, col_list])
# Paste relevant colums together
df_sub$paste_col <- do.call(paste, c(df_sub[, col_list], sep = '_'))
# Exclude duplicated values
df_sub <- df_sub[!duplicated(df_sub$paste_col), ]
return(df_sub)
}
现在我定义要创建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))
map
将vector或list作为参数,并将指定的函数应用于每个元素(如lapply
)。比较df_sub1
和plot_sub
的第一个元素以查看差异。
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
新的互动已添加到df_sub1
。
要提取匹配和唯一值,我在inner_join
- 列和不同的anti_join
&#39>上使用plot_sub
和df_sub
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))
inner_join
返回所有行,这些行在by
- 参数中指定的列中具有匹配值,而anti_join
返回df_sub
的所有行,这些行是map2
不匹配。
这里我使用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
- 函数,它接受两个向量/列表并应用指定的函数。
match
在最后一步中,我提取每个unique
和res_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)
。
map_int
这里我使用map
,因为我的返回值是一个整数,我想直接在总和中使用它。仅使用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 = '_')
数据强>
matrix = [[None]*length]*length