使用多行展开R数据框中的每一行

时间:2018-01-22 16:43:04

标签: r dataframe dplyr

我需要一个包含某些文件名称的数据框,这些文件与映射到这些文件中每行的模式相匹配。我的问题是,我无法为每一行生成多行,数据框应按列和行增长,每行展开。我需要的基本上是左外连接,但我正在努力学习语法。

library(dplyr)

app.lsts <- data.frame(
  file=list.files(path='.', pattern='app.lst', recursive=TRUE)
) %>%
  mutate(command=paste0('cat ', file)) %>%
  mutate(packages=system(command, intern=TRUE))

最后一个mutate不起作用,因为packages是一个行列表。我如何“打开”这些?

1 个答案:

答案 0 :(得分:1)

首先,一些工作(但不是很好的代码):

require(tidyverse)
out_df <- 
    list.files(path='.', pattern='*.foo', recursive=TRUE) %>%
    map(~readLines(file(.x))) %>% 
    setNames(fnames) %>%
    t %>%
    as.data.frame %>%
    gather(file, lines) %>%
    unnest()

out_df

这是一个tidyverse风格的命令,用于生成我认为您想要的数据。由于我没有您的输入文件,我编写了这些示例文件:

f1.foo

的内容
line_1_f1
line_2_f1

f2.foo

的内容
line_1_f2
line_2_f2
line_3_f2

相对于您的方法的变化:

  1. 避免使用内置函数file()作为列名。我改为使用fname
  2. 不要使用system来读取文件,有内置的R函数可以做到这一点。使用system()不必要地使您的代码移植到其他操作系统更不可能成功。
  3. 在将所有数据读入R之后构建数据帧,而不是之前。由于dplyr的非标准评估方式有效,因此在readLines(...)内部mutate()很难使用要读取的文件连接的purrr::map()

  4. 使用setNames()从文件名列表中生成文件内容行列表。这是编写for循环的一种整合方式。

  5. 使用t()设置列表元素的名称。
  6. 使用as.data.frame()gather()
  7. 将此列表固定到data.frame中
  8. 使用unnest()整理数据,将每个文件有一列的数据框折叠到每行一个文件的数据框中。
  9. 使用fnames <- list.files(path='.', pattern='*.foo', recursive=TRUE) out_df <- data.frame(fname = c(), lines=c()) for(fname in fnames){ fcontents <- readLines(file(fname)) %>% as.character this_df <- data.frame(fname = fname, lines = fcontents) out_df <- bind_rows(out_df, this_df) } 展开列表。
  10. 我不认为这种方法非常漂亮,但它确实有效。避免丑陋的步骤5和6的另一种方法是for循环。

       fname     lines
    1 f1.foo line_1_f1
    2 f1.foo line_2_f1
    3 f2.foo line_1_f2
    4 f2.foo line_2_f2
    5 f2.foo line_3_f2
    

    两种情况下的输出都是

    BEGIN()