首页 > 解决方案 > 在 R 中循环遍历数据帧的不同子集

问题描述

我在 R 中有一个数据框,看起来像这样:

library(tibble)

df <- tribble(~Word1, ~Word2, ~distance, ~speaker, ~session,
          "WordA", "WordX", 0.14, "JB", 1,
          "WordB", "WordY", 0.21, "JB", 1,
          "WordC", "WordZ", 0.47, "JB", 1,
          "WordX", "WordA", 0.23, "JB", 1,
          "WordY", "WordB", 0.78, "JB", 1,
          "WordZ", "WordC", 0.51, "JB", 1)

我想创建一个元素列表,其中计算因距离而异的数据。例如,我使用子集对数据运行了以下计算distance < 1

df %>%
    filter(distance < 0.1) %>%
    group_by(speaker, session, Word1) %>%
    tally()     # for each item in Word1, how many times does Word2 have a distance <1?

我想对 0-1 的不同距离执行此操作,增量为 0.001。使用这个查询,我已经做到了这一点:

threshold_list <- seq(from = 0, to = 1, by = 0.01)  # create an empty list with 101 elements
thresholds <- seq(from = 0, to = 1, by = 0.01)      # create a df with distance thresholds
 
for(t in 1:thresholds){
    threshold_list[[t]] <- filter(df, distance < t) %>% 
    group_by(speaker, session, Word1) %>% 
    tally() 
}

当我运行它时,我得到了错误

threshold_list[[t]] <- filter(df, distance < t) %>% group_by(speaker, : 提供的元素多于要替换的元素另外:警告消息:在 1:thresholds 中:数值表达式有 101 个元素: 只有第一个使用

我认为这与 listthreshold_list和 df之间缺乏匹配有关thresholds,但我是循环的新手,并且有点不知道如何前进!

标签: rfor-loop

解决方案


我不确定我是否理解您尝试应用于这些子集的函数,但希望这种在子集数据上运行函数的逻辑能够成立。

所以我在我的解决方案中所做的是使用嵌套来完成子集。

Hadley Wickham 在 R for Data Science 的嵌套章节中讨论了这个逻辑

本质上,我们是在数据帧中创建数据帧,并分别对每个数据帧应用一个函数。

因此,在下面我从您提供的示例表开始。我创建了一个距离度量,允许您根据 0.001 的增量对结果进行分组。然后我将数据嵌套在那个新的距离度量上。所以这里是我们为每个距离切割度量创建一个数据框的地方

然后我们可以使用 purrr::map 将统计函数应用于每个数据帧中的所有内容。

与所有循环相比,我更喜欢这种方法,因为代码最终变得更干净,更容易推理。

library(tibble)
library(dplyr)
library(purrr)

df <- tribble(~Word1, ~Word2, ~distance, ~speaker, ~session,
              "WordA", "WordX", 0.14, "JB", 1,
              "WordA", "WordY", 0.14, "JB", 1,
              "WordB", "WordY", 0.21, "JB", 1,
              "WordC", "WordZ", 0.47, "JB", 1,
              "WordX", "WordA", 0.23, "JB", 1,
              "WordY", "WordB", 0.78, "JB", 1,
              "WordZ", "WordC", 0.51, "JB", 1)


df_2 <- df %>% 
        mutate(distance_cut = as.numeric(cut(distance, 
                                  breaks = c(seq(0, 1, by =  0.001)))) / 1000)

df_2 <- df_2 %>% 
        group_by(distance_cut) %>% 
        nest()


grouped_tally <- function(d) {
        d %>% 
                group_by(speaker, session, Word1) %>%  
                tally()
}

df_2 <- df_2 %>% 
        mutate(results = map(data, grouped_tally))

unnest(df_2, results)

推荐阅读