【问题标题】:sapply vs. lapply while reading files and rbind'ing themsapply 与 lapply 在读取文件和 rbind 时
【发布时间】:2016-09-23 17:50:13
【问题描述】:

我按照 Hadley 的线程:Issue in Loading multiple .csv files into single dataframe in R using rbind 读取多个 CSV 文件,然后将它们转换为一个数据帧。我还试验了lapplysapply,如Grouping functions (tapply, by, aggregate) and the *apply family 所述。

这是我的第一个 CSV 文件:

dput(File1)
structure(list(First.Name = structure(c(1L, 2L, 1L, 1L, 1L), .Label = c("A", 
"C"), class = "factor"), Last.Name = structure(c(1L, 2L, 2L, 
2L, 2L), .Label = c("B", "D"), class = "factor"), Income = c(55L, 
23L, 34L, 45L, 44L), Tax = c(23L, 21L, 22L, 24L, 25L), Location = structure(c(3L, 
3L, 1L, 4L, 2L), .Label = c("Americas", "AP", "EMEA", "LATAM"
), class = "factor")), .Names = c("First.Name", "Last.Name", 
"Income", "Tax", "Location"), class = "data.frame", row.names = c(NA, 
-5L))

这是我的第二个 CSV 文件:

dput(File2)
structure(list(First.Name = structure(c(1L, 2L, 1L, 1L, 1L), .Label = c("A", 
"C"), class = "factor"), Last.Name = structure(c(1L, 2L, 2L, 
2L, 2L), .Label = c("B", "D"), class = "factor"), Income = c(55L, 
55L, 55L, 55L, 55L), Tax = c(24L, 24L, 24L, 24L, 24L), Location = structure(c(3L, 
3L, 1L, 4L, 2L), .Label = c("Americas", "AP", "EMEA", "LATAM"
), class = "factor")), .Names = c("First.Name", "Last.Name", 
"Income", "Tax", "Location"), class = "data.frame", row.names = c(NA, 
-5L))

这是我的代码:

dat1 <-",First.Name,Last.Name,Income,Tax,Location\n1,A,B,55,23,EMEA\n2,C,D,23,21,EMEA\n3,A,D,34,22,Americas\n4,A,D,45,24,LATAM\n5,A,D,44,25,AP"
dat2 <-",First.Name,Last.Name,Income,Tax,Location\n1,A,B,55,24,EMEA\n2,C,D,55,24,EMEA\n3,A,D,55,24,Americas\n4,A,D,55,24,LATAM\n5,A,D,55,24,AP"

tc1 <- textConnection(dat1)
tc2 <- textConnection(dat2)

merged_file <- do.call(rbind, lapply(list(tc1,tc2), read.csv))

虽然效果很好,但我想将 lapply 更改为 sapply。从上面的线程中,我意识到sapply 会将读取因子从csv 文件更改为矩阵,但我不确定为什么会翻转这些字段。例如,Income 字段占用第 3 行和第 8 行,但不在一列中。

代码如下:

tc1 <- textConnection(dat1)
tc2 <- textConnection(dat2)

# change lapply to sapply    
merged_file <- do.call(rbind, sapply(list(tc1,tc2), read.csv))

这是输出:

    [,1] [,2] [,3] [,4] [,5]
 [1,]    1    2    1    1    1
 [2,]    1    2    2    2    2
 [3,]   55   23   34   45   44
 [4,]   23   21   22   24   25
 [5,]    3    3    1    4    2
 [6,]    1    2    1    1    1
 [7,]    1    2    2    2    2
 [8,]   55   55   55   55   55
 [9,]   24   24   24   24   24
[10,]    3    3    1    4    2

如果有任何帮助,我将不胜感激。我对 R 相当陌生,不确定发生了什么。

【问题讨论】:

  • 为什么要把lapply改成sapplylapply 是这里合适的函数,效率更高。顺便说一句,paste 是矢量化的。
  • @RichScriven - 我只是在尝试了解使用sapply 而不是lapply 时输出不同的原因。
  • “虽然这很好用” 作为一个可重现的例子,它甚至根本不起作用。我们没有你的路径,所以它会失败。从 textConnection() 而不是文件中读取数据帧是最简单的。我编辑了你的代码。
  • 这个问题与因素无关,它是通用的 sapply 与 lapply。与Why does sapply return a matrix that I need to transpose... 重复

标签: r sapply rbind read.csv


【解决方案1】:

这个问题与因素无关,它是通用的sapply vs lapply。 为什么sapply 搞错了,而lapply 搞对了? 请记住,在 R 中,数据框是列列表。每列可以有不同的类型。

  • lapply 将列列表返回给rbind,它可以正确地进行连接。它将相应的列保持在一起。所以你的因素正确地出现了。
  • sapply 然而...
    • 返回一个数字矩阵...(因为矩阵只能有一种类型,与数据框不同)
    • ...更糟糕的是,has an unwanted transpose
    • 所以sapply 将您的两个 5x6 输入数据帧转换为转置的 6x5 矩阵(列现在对应于行)...
    • 所有数据都被强制转换为数字(垃圾!)。
    • 然后rbind 行-“连接”这两个垃圾 6x5 数字矩阵到一个非常垃圾的 12x5 矩阵。由于列已被转置为行,因此将矩阵进行行连接会组合数据类型,显然您的因素搞砸了。

总结:只需使用lapply

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-09-29
    • 1970-01-01
    • 2023-03-06
    • 1970-01-01
    • 2010-11-26
    • 2020-05-03
    • 1970-01-01
    相关资源
    最近更新 更多