我正在分析一个具有200行和1200列的数据集,该数据集存储在.CSV
文件中。为了进行处理,我使用R的read.csv()
函数读取了此文件。
R花费≈600秒来读取此数据集。后来我有了一个主意,我将数据转换到.CSV
文件中,并尝试使用read.csv()
函数再次读取。看到这只花了大约20秒,我感到很惊讶。如您所见,它快了大约30倍。
我对以下迭代进行了验证:
> system.time(dat <- read.csv(file = "data.csv", sep = ",", header = F))
user system elapsed
610.98 6.54 618.42 # 1st iteration
568.27 5.83 574.47 # 2nd iteration
521.13 4.73 525.97 # 3rd iteration
618.31 3.11 621.98 # 4th iteration
603.85 3.29 607.50 # 5th iteration
> system.time(dat <- read.csv(file = "data_transposed.csv",
sep = ",", header = F))
user system elapsed
17.23 0.73 17.97 # 1st iteration
17.11 0.69 17.79 # 2nd iteration
20.70 0.89 21.61 # 3rd iteration
18.28 0.82 19.11 # 4th iteration
18.37 1.61 20.01 # 5th iteration
在任何数据集中,我们在行和列中进行观察,其中包含要观察的变量。转置会更改此数据结构。 将数据转置进行处理是一种好习惯吗,即使它使数据看起来很奇怪?
我想知道什么使R在转置数据时快速读取数据集。我敢肯定是因为更早的尺寸是200 * 1200
,它在转置操作后变成了1200 * 200
。
为什么我转置数据时R会快速读取数据?
我最初问这个问题是因为我的RStudio花很长时间读取和计算高维数据集(与行[200行,1200列]相比,有许多列)。我正在使用内置的R函数read.csv()
。我阅读了以下评论,根据他们的建议,后来我尝试使用read.csv2()
和fread()
函数,它们都可以正常工作,但是它们对原始数据集[200行* 1200列]的运行速度很慢,并且读取了转置后的数据-设置更快。
我注意到,这对 MS-Excel 和 Libre office Calc 也同样有效。我什至试图将其打开到 Sublime Text Editor 中,即使对于此文本编辑器,它也很容易(快速)读取转置数据。我仍然无法弄清所有这些应用程序如何表现出来的原因。如果您的数据中的列数比行数多,所有这些应用程序都会遇到麻烦。
所以要总结整个故事,我只有3个问题。
我的实验也许帮助我重新发现了一些“ 已经知道的” 智慧,但我在互联网上找不到任何相关内容。好心地 分享这种良好的编程/数据分析实践。
答案 0 :(得分:7)
您的问题基本上是关于:读取长数据集比读取宽数据集快得多吗?
我在这里给出的不是最终答案,而是一个新的起点。
对于任何与性能相关的问题,进行概要分析总是比猜测更好。 system.time
很好,但是它只告诉您总的运行时间,而不是内部时间的分配方式。如果您快速浏览了read.table
的源代码(read.csv
仅仅是read.table
的包装),则它包含三个阶段:
scan
读取5行数据。我不确定这部分的目的; scan
以读取您的完整数据。基本上,这会将您的数据逐列读入一个字符串列表,其中每一列都是一个“记录”; type.convert
隐式地进行,也可以由as.numeric
,as.Date
等地进行显式(如果您已指定列类)。前两个阶段是在C级别完成的,而最后阶段是在R级别,并通过for循环遍历所有记录。
基本的分析工具是Rprof
和summaryRprof
。以下是一个非常非常简单的示例。
## configure size
m <- 10000
n <- 100
## a very very simple example, where all data are numeric
x <- runif(m * n)
## long and wide .csv
write.csv(matrix(x, m, n), file = "long.csv", row.names = FALSE, quote = FALSE)
write.csv(matrix(x, n, m), file = "wide.csv", row.names = FALSE, quote = FALSE)
## profiling (sample stage)
Rprof("long.out")
long <- read.csv("long.csv")
Rprof(NULL)
Rprof("wide.out")
wide <- read.csv("wide.csv")
Rprof(NULL)
## profiling (report stage)
summaryRprof("long.out")[c(2, 4)]
summaryRprof("wide.out")[c(2, 4)]
c(2, 4)
提取所有具有足够样本数和“ CPU总时间”(可能低于挂钟时间)的R级函数的“总”时间。以下是我在Sandy Bridge 2011上的 intel i5 2557m @ 1.1GHz(禁用涡轮增压)上得到的东西。
## "long.csv"
#$by.total
# total.time total.pct self.time self.pct
#"read.csv" 7.0 100 0.0 0
#"read.table" 7.0 100 0.0 0
#"scan" 6.3 90 6.3 90
#".External2" 0.7 10 0.7 10
#"type.convert" 0.7 10 0.0 0
#
#$sampling.time
#[1] 7
## "wide.csv"
#$by.total
# total.time total.pct self.time self.pct
#"read.table" 25.86 100.00 0.06 0.23
#"read.csv" 25.86 100.00 0.00 0.00
#"scan" 23.22 89.79 23.22 89.79
#"type.convert" 2.22 8.58 0.38 1.47
#"match.arg" 1.20 4.64 0.46 1.78
#"eval" 0.66 2.55 0.12 0.46
#".External2" 0.64 2.47 0.64 2.47
#"parent.frame" 0.50 1.93 0.50 1.93
#".External" 0.30 1.16 0.30 1.16
#"formals" 0.08 0.31 0.04 0.15
#"make.names" 0.04 0.15 0.04 0.15
#"sys.function" 0.04 0.15 0.02 0.08
#"as.character" 0.02 0.08 0.02 0.08
#"c" 0.02 0.08 0.02 0.08
#"lapply" 0.02 0.08 0.02 0.08
#"sys.parent" 0.02 0.08 0.02 0.08
#"sapply" 0.02 0.08 0.00 0.00
#
#$sampling.time
#[1] 25.86
因此,读取长数据集需要7s CPU时间,而读取宽数据集则需要25.86s CPU时间。
乍一看可能会感到困惑,因为在更广泛的情况下报告了更多的功能。实际上,长案例和宽案例都执行相同的功能集,但长案例的执行速度更快,因此许多函数所花费的时间少于采样间隔(0.02s),因此无法测量。
但是无论如何,运行时间主要由scan
和type.convert
(隐式类型转换)决定。在这个例子中,我们看到了
scan
基本上就是read.csv
的全部工作对象,但是不幸的是,我们无法将这样的时间进一步划分为第一阶段和第二阶段。不要认为这是理所当然的,因为阶段1只读取5行,所以它会非常快。实际上,在调试模式下,我发现阶段1可能花费很长时间。那我们下一步该怎么做?
scan
; 答案 1 :(得分:1)
与长数据集(即转置的数据集)相比,宽数据集通常更慢地读入内存。这会影响许多读取数据的程序,例如R,Python,Excel等,尽管此说明与R更相关:
NA
。这意味着每一列至少具有与csv文件中的行数一样多的单元格,而在较长的数据集中,您可以删除NA
值并节省一些空间由于您的数据集似乎不包含任何NA
值,因此我的直觉是由于第二点,您看到了速度的提高。您可以通过将colClasses = rep('numeric', 20)
传递给read.csv
或fread
来获取20列数据集,或者将rep('numeric', 120)
传递给120列数据来测试这一理论,这将减少猜测的开销数据类型。