Создать новые тиблы для каждого элемента в векторе или столбце - PullRequest
2 голосов
/ 18 января 2020

У меня есть tibble / dataframe под названием sections, который я хочу использовать для создания нескольких новых tibbles / dataframe. Я хочу перебрать каждую строку и создать новый тиббл для каждого. Первый столбец содержит имя нового тибла, а второй и третий столбцы содержат индексы для использования в другом тибле, называемом my_text.

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 

Есть ли какой-нибудь способ эффективно сделать это с помощью al oop или другой конструкции?

Ответы [ 2 ]

1 голос
/ 18 января 2020

Мы можем использовать pmap для создания list из tibble с, и если нам нужны отдельные объекты в глобальной среде (не рекомендуется), используйте 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 l oop

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]])
   }
0 голосов
/ 19 января 2020

Мы можем создать последовательность между begin_row и end_row, получить данные в длинном формате и сделать столбец inner_join с my_text после добавления столбца row_number().

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 

Это вернет один фрейм данных со всеми необходимыми строками в нем, если вам нужны отдельные фреймы данных, добавьте %>% group_split(sections) в цепочке после последнего шага, т.е. inner_join.

...