【问题标题】:Create new tibbles for each element in a vector or column为向量或列中的每个元素创建新的小标题
【发布时间】:2020-01-18 16:53:11
【问题描述】:

我有一个名为sections 的小标题/数据框,我想用它来创建几个新的小标题/数据框。我想遍历每一行并为每一行创建一个新的小标题。第一列提供新 tibble 的名称,第二列和第三列提供在另一个名为 my_text 的 tibble 上使用的索引。

sections <- structure(list(sections = c("cash_and_bank_sweep", "money_market_funds_non-sweep", 
                                    "equities"), 
                       begin_row = c(325L, 345L, 357L), 
                       end_row = c(345L, 357L, 384L)), 
                  class = c("tbl_df", "tbl", "data.frame"), 
                  row.names = c(NA, -3L))
> sections
# A tibble: 3 x 3
  sections                     begin_row end_row
  <chr>                            <int>   <int>
1 cash_and_bank_sweep                325     345
2 money_market_funds_non-sweep       345     357
3 equities                           357     384
set.seed(1)
my_text <- tibble(Strings = sample(letters, size = 1000, replace = TRUE)

> head(my_text)
# A tibble: 6 x 1
  Strings
  <chr>  
1 y      
2 d      
3 g      
4 a      
5 b      
6 w 

所以我想创建的第一个小标题是cash_and_bank_sweep。手动我可以创建如下:

cash_and_bank_sweep <- tibble(Strings = my_text$Strings[sections$begin_row[1]:sections$end_row[1]])

> head(cash_and_bank_sweep)
# A tibble: 6 x 1
  Strings
  <chr>  
1 e      
2 n      
3 e      
4 k      
5 k      
6 q 

有没有办法通过循环或其他结构有效地做到这一点?

【问题讨论】:

    标签: r dataframe tibble


    【解决方案1】:

    我们可以使用pmap 来创建tibbles 的list,如果我们需要作为全局环境中的单个对象(不推荐),请使用list2env

    library(purrr)
    lst1 <- pmap(sections[-1], ~ tibble(Strings = my_text$Strings[..1:..2]))
    names(lst1) <- sections[[1]]
    
    list2env(lst1, .GlobalEnv)
    

    或者另一个选项是map2

    lst1 <- map2(sections$begin_row, sections$end_row,
                 ~ tibble(Strings = my_text$Strings[.x:.y]))
    names(lst1) <- sections[[1]]
    

    base R 中,这可以通过Map 完成

    lst1 <- Map(function(i, j) data.frame(Strings = my_text$Strings[i:j]), 
                sections$begin_row, sections$end_row)
    names(lst1) <- sections[[1]]
    

    或者使用for 循环

    lst1 <- vector('list', nrow(sections))
    names(lst1) <- sections[[1]]
    for(i in seq_along(lst1)) {
        lst1[[i]] <- data.frame(Strings = my_text$Strings[sections$begin_row[i]:sections$end_row[i]])
       }
    

    【讨论】:

    • 哇,很好的答案。您的第一种方法效果很好,我将尝试学习该方法。感谢您的多个回答。
    【解决方案2】:

    我们可以在begin_rowend_row 之间创建一个序列,并获取长格式的数据,并在添加row_number() 列后使用my_text 列执行inner_join

    library(tidyverse)
    
    sections %>%
      mutate(value = map2(begin_row, end_row, `:`)) %>%
      unnest(value) %>%
      select(-begin_row, -end_row) %>%
      inner_join(my_text %>% mutate(row = row_number()), by = c('value' = 'row'))
    
    # A tibble: 62 x 3
    #  sections            value Strings
    #   <chr>               <int> <chr>  
    # 1 cash_and_bank_sweep   325 e      
    # 2 cash_and_bank_sweep   326 n      
    # 3 cash_and_bank_sweep   327 e      
    # 4 cash_and_bank_sweep   328 k      
    # 5 cash_and_bank_sweep   329 k      
    # 6 cash_and_bank_sweep   330 q      
    # 7 cash_and_bank_sweep   331 a      
    # 8 cash_and_bank_sweep   332 z      
    # 9 cash_and_bank_sweep   333 m      
    #10 cash_and_bank_sweep   334 a      
    # … with 52 more rows 
    

    这将返回一个包含所有必需行的数据帧,如果您需要单独的数据帧,请在最后一步之后的链中添加%&gt;% group_split(sections),即inner_join

    【讨论】:

      猜你喜欢
      • 2021-11-17
      • 1970-01-01
      • 1970-01-01
      • 2022-11-13
      • 1970-01-01
      • 2018-02-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多