data文件与csv文件
正如我已经在几篇博客文章中提到的那样,我一直在探索土地注册处的价格支付数据集 ,尽管我最初一直在使用SparkR,但我很好奇使用纯R探索数据集有多么容易。
我以为我会先将数据加载到数据帧中,然后使用部署程序运行相同的查询。
我之前遇到过Hadley Wickham的阅读器库,但没有使用过,并且由于我需要加载2000万行CSV文件,因此这似乎是尝试的最佳时机。
readr的目标是提供一种快速友好的方式来将表格数据读入R。
让我们开始吧:
> library(readr)
> system.time(read_csv("pp-complete.csv", col_names = FALSE))
user system elapsed
127.367 21.957 159.963
> df = read_csv("pp-complete.csv", col_names = FALSE)
因此,将CSV文件处理为数据框花了2分钟多的时间。 让我们快速看一下它的内容:
> head(df)
Source: local data frame [6 x 16]
X1 X2 X3 X4 X5 X6 X7 X8 X9
(chr) (int) (date) (chr) (chr) (chr) (chr) (chr) (chr)
1 {0C7ADEF5-878D-4066-B785-0000003ED74A} 163000 <NA> UB5 4PJ T N F 106
2 {35F67271-ABD4-40DA-AB09-00000085B9D3} 247500 <NA> TA19 9DD D N F 58
3 {B20B1C74-E8E1-4137-AB3E-0000011DF342} 320000 <NA> W4 1DZ F N L 58
4 {7D6B0915-C56B-4275-AF9B-00000156BCE7} 104000 <NA> NE61 2BH D N F 17
5 {47B60101-B64C-413D-8F60-000002F1692D} 147995 <NA> PE33 0RU D N F 4
6 {51F797CA-7BEB-4958-821F-000003E464AE} 110000 <NA> NR35 2SF T N F 5
Variables not shown: X10 (chr), X11 (chr), X12 (chr), X13 (chr), X14 (chr), X15 (chr), address (chr)
现在,让我们查询数据框以查看哪个邮政编码的平均售价最高。 在应用一些聚合函数之前,我们需要对“ X4”列进行分组:
> library(dplyr)
> system.time(df %>%
group_by(X4) %>%
summarise(total = sum(as.numeric(X2)), count = n(), ave = total / count) %>%
arrange(desc(ave)))
user system elapsed
122.557 1.135 124.211
Source: local data frame [1,164,396 x 4]
X4 total count ave
(chr) (dbl) (int) (dbl)
1 SW7 1DW 39000000 1 39000000
2 SW1W 0NH 32477000 1 32477000
3 W1K 7PX 27000000 1 27000000
4 SW1Y 6HD 24750000 1 24750000
5 SW6 1BA 18000000 1 18000000
6 SW1X 7EE 101505645 6 16917608
7 N6 4LA 16850000 1 16850000
8 EC4N 5AE 16500000 1 16500000
9 W8 7EA 82075000 6 13679167
10 W1K 1DP 13500000 1 13500000
如果要查找有史以来最昂贵的房地产,而不是邮政编码的平ASP格怎么办?
> system.time(df %>% group_by(X4) %>% summarise(max = max(X2)) %>% arrange(desc(max)))
user system elapsed
35.438 0.478 36.026
Source: local data frame [1,164,396 x 2]
X4 max
(chr) (int)
1 SW10 9SU 54959000
2 SW7 1QJ 50000000
3 SW1X 8HG 46013365
4 SW7 1DW 39000000
5 SW1W 0NH 32477000
6 SW1X 7LJ 29350000
7 W8 7EA 27900000
8 SW3 3SR 27750000
9 W1K 7PX 27000000
10 SW1X 7EE 25533000
.. ... ...
有趣的是,尽管看起来我们所做的工作只是少了一点,但它比第一个要快得多。
在这一点上,我向Ashok提到了我的实验,他建议我给data.table一个尝试,看看效果是否更好。 我以前没有使用过它,但是能够使其Swift启动并运行 :
> library(data.table)
> system.time(fread("pp-complete.csv", header = FALSE))
Read 20075122 rows and 15 (of 15) columns from 3.221 GB file in 00:01:05
user system elapsed
59.324 5.798 68.956
> dt = fread("pp-complete.csv", header = FALSE)
> head(dt)
V1 V2 V3 V4 V5 V6 V7 V8 V9
1: {0C7ADEF5-878D-4066-B785-0000003ED74A} 163000 2003-02-21 00:00 UB5 4PJ T N F 106
2: {35F67271-ABD4-40DA-AB09-00000085B9D3} 247500 2005-07-15 00:00 TA19 9DD D N F 58
3: {B20B1C74-E8E1-4137-AB3E-0000011DF342} 320000 2010-09-10 00:00 W4 1DZ F N L 58
4: {7D6B0915-C56B-4275-AF9B-00000156BCE7} 104000 1997-08-27 00:00 NE61 2BH D N F 17
5: {47B60101-B64C-413D-8F60-000002F1692D} 147995 2003-05-02 00:00 PE33 0RU D N F 4
6: {51F797CA-7BEB-4958-821F-000003E464AE} 110000 2013-03-22 00:00 NR35 2SF T N F 5
V10 V11 V12 V13 V14 V15
1: READING ROAD NORTHOLT NORTHOLT EALING GREATER LONDON A
2: ADAMS MEADOW ILMINSTER ILMINSTER SOUTH SOMERSET SOMERSET A
3: WHELLOCK ROAD LONDON EALING GREATER LONDON A
4: WESTGATE MORPETH MORPETH CASTLE MORPETH NORTHUMBERLAND A
5: MASON GARDENS WEST WINCH KING'S LYNN KING'S LYNN AND WEST NORFOLK NORFOLK A
6: WILD FLOWER WAY DITCHINGHAM BUNGAY SOUTH NORFOLK NORFOLK A
因此,我们已经在解析时间内获得了1分钟的时间,这非常不错。 让我们尝试找到平ASP格最高的邮政编码:
> dt[,list(length(V2), sum(V2)), by=V4][, V2 / V1, by=V4][order(-V1)][1:10]
Error in sum(V2) : invalid 'type' (character) of argument
嗯,似乎我们需要将列“ V2”设为数字。 让我们这样做:
> dt = dt[, V2:= as.numeric(V2)]
> dt[,list(length(V2), sum(V2)), by=V4][, V2 / V1, by=V4][order(-V1)][1:10]
user system elapsed
5.108 0.670 6.183
V4 V1
1: SW7 1DW 39000000
2: SW1W 0NH 32477000
3: W1K 7PX 27000000
4: SW1Y 6HD 24750000
5: SW6 1BA 18000000
6: SW1X 7EE 16917608
7: N6 4LA 16850000
8: EC4N 5AE 16500000
9: W8 7EA 13679167
10: W1K 1DP 13500000
这比我们的数据框版本要快得多–约5秒,而约2分钟。 我们已经失去了总销售额和销售列数,但是我希望那仅仅是因为我的data.table foo很弱,如果需要的话我们可以保留它们。
但是在执行时间方面是一个好的开始。 现在,让我们通过邮政编码查询来尝试最高销售价格:
> system.time(dt[,list(max(V2)), by=V4][order(-V1)][1:10])
user system elapsed
3.684 0.358 4.132
V4 V1
1: SW10 9SU 54959000
2: SW7 1QJ 50000000
3: SW1X 8HG 46013365
4: SW7 1DW 39000000
5: SW1W 0NH 32477000
6: SW1X 7LJ 29350000
7: W8 7EA 27900000
8: SW3 3SR 27750000
9: W1K 7PX 27000000
10: SW1X 7EE 25533000
我们获得了与以前相同的结果,这次花费了〜4秒,而花费了〜35秒。
如果将邮政编码列设置为键,我们实际上可以做得更好:
> setkey(dt, V4)
> system.time(dt[,list(length(V2), sum(V2)), by=V4][, V2 / V1, by=V4][order(-V1)][1:10])
user system elapsed
1.500 0.047 1.548
> system.time(dt[,list(max(V2)), by=V4][order(-V1)][1:10])
user system elapsed
0.578 0.026 0.604
就我的实验而言, 如果还有其他方法可以使两个版本中的任何一个更快进行,请在评论中告知我。
哦,还有关于我们可以从查询中学到什么的评论……骑士桥是一个非常昂贵的生活区!
data文件与csv文件