【问题标题】:lapply over lapply (or other way to clean timeseries data)lapply over lapply(或其他清理时间序列数据的方式)
【发布时间】:2019-12-03 14:59:47
【问题描述】:

我正在尝试从许多格式不整齐的 Excel 电子表格中提取一些数据。我想我需要在 lapply 内运行 lapply,但似乎无法使其工作。这是一个例子:

这里有两个数据框,其格式与我在 excel 表中找到的相同:

library('dplyr')
library('tidyr')
library('readxl')

df1 <- data.frame(instance = c('...', 'A', 'B'), 
                  `1990.1` = c('est', 1, 2), 
                  `1990.2` = c('val', 2, 3),
                  `1991.1` = c('est', 3, 4),
                  `1991.2` = c('val', 4, 5))


df2 <- data.frame(instance = c('...', 'A', 'B'),
                  `1990.1` = c('est', 5, 6), 
                  `1990.2` = c('val', 6, 7),
                  `1991.1` = c('est', 7, 8),
                  `1991.2` = c('val', 8, 9))
> df1
  instance X1990.1 X1990.2 X1991.1 X1991.2
1      ...     est     val     est     val
2        A       1       2       3       4
3        B       2       3       4       5

我创建了一个函数来清理数据:

df1 %>%  
  select(1, which(.[1,] == 'est')) %>%
  .[-1,] %>%
  gather(key = year, value = score, -instance) %>%
  mutate(var = 'est')

  instance    year score var
1        A X1990.1     1 est
2        B X1990.1     2 est
3        A X1991.1     3 est
4        B X1991.1     4 est

给予:

data_clean <- function(x) {
  df1 %>% 
    select(1, which(.[1,] == x)) %>%
    .[-1,] %>%
    gather(key = year, value = score, -instance) %>%
    mutate(var = x) 
}

我现在可以生成每个 df 的干净版本,如下所示:

do.call(rbind, lapply(c('est', 'val'), data_clean)) %>% 
  mutate(origin = 'df1')

  instance    year score var origin
1        A X1990.1     1 est    df1
2        B X1990.1     2 est    df1
3        A X1991.1     3 est    df1
4        B X1991.1     4 est    df1
5        A X1990.2     2 val    df1
6        B X1990.2     3 val    df1
7        A X1991.2     4 val    df1
8        B X1991.2     5 val    df1

我现在需要做的是将其应用于数据框列表:

list_data <- list(df1, df2)

在我的例子中,我会从一个函数中生成这个:

data_pull <- function(x) {
  read_excel('path/to/file', sheet = x)
}

list_data <- lapply(2:20, data_pull)

但我想不出该怎么做。我需要将 data_clean 应用于 data_pull 生成的列表的每个元素。我显然需要删除 data_clean 函数中对 df 的第一次调用,但是我将什么对象传递给 data_clean?

我最终想要的是一个单一的数据框,将所有数据以整齐的格式集中在一个地方。

对不起,如果我在这里遗漏了一些简单的东西。我觉得有很多这样的结构数据,清理它的解决方案应该相当简单。我似乎无法想到它。

【问题讨论】:

    标签: r lapply


    【解决方案1】:

    一种选择是将其保存在list 中,并使用map 循环遍历列表。我们可以通过paste将第一行重命名为除“实例”之外的所有列,slice 第一行,使用pivot_longer 将“宽”重塑为“长”,separate 'name' 列一分为二,并根据需要转换 type

    library(dplyr)
    library(tidyr)
    library(purrr)
    library(readr)
    library(stringr)
    f1 <- function(dat) {
            names(dat)[-1] <- str_c(names(dat)[-1], unlist(dat[1,-1]), sep="_")
            dat %>%
               slice(-1) %>%
               pivot_longer(cols = -instance, values_to = "seq" ) %>%
               mutate_all(as.character) %>%
               separate(name, into = c('year', 'var'), sep="_", convert = TRUE) %>%
               type_convert()
    
    }
    
    
    
    
    map_dfr(set_names(list_data, c('df1', 'df2')), f1, .id = 'origin')
    # A tibble: 16 x 5
    #  origin instance year    var     seq
    #   <chr>  <chr>    <chr>   <chr> <dbl>
    # 1 df1    A        X1990.1 est       1
    # 2 df1    A        X1990.2 val       2
    # 3 df1    A        X1991.1 est       3
    # 4 df1    A        X1991.2 val       4
    # 5 df1    B        X1990.1 est       2
    # 6 df1    B        X1990.2 val       3
    # 7 df1    B        X1991.1 est       4
    # 8 df1    B        X1991.2 val       5
    # 9 df2    A        X1990.1 est       5
    #10 df2    A        X1990.2 val       6
    #11 df2    A        X1991.1 est       7
    #12 df2    A        X1991.2 val       8
    #13 df2    B        X1990.1 est       6
    #14 df2    B        X1990.2 val       7
    #15 df2    B        X1991.1 est       8
    #16 df2    B        X1991.2 val       9
    

    如果我们使用函数data_pull

    map_dfr(2:20, ~ data_pull(.x) %>%
                     f1, .id = 'origin')
    

    【讨论】:

    • 谢谢。慢慢地完成它的工作。一个挑战,我似乎无法运行pivot_longer()。我收到错误消息:Error in pivot_longer(., cols = -instance, values_to = "seq") : could not find function "pivot_longer" 我已经安装并加载了 tidyrpurrrreadr
    • @MorrisseyJ 在tidyr 1.0.0中介绍。你能检查你的packageVersion('tidyr')
    • 是的,就是这样。谢谢,我没有意识到包已经过时了。
    猜你喜欢
    • 2018-11-29
    • 1970-01-01
    • 2022-11-10
    • 2020-12-21
    • 1970-01-01
    • 2020-07-07
    • 2013-06-21
    • 1970-01-01
    • 2020-06-05
    相关资源
    最近更新 更多