dplyr是一个R包,用来处理R环境内外的结构化数据。dplyr使得R语言使用者更简单、一致、高效地处理数据。使用dplyr包处理spark数据集,功能包括:
1、读取数据
可以使用以下函数将数据读入spark数据集:
无论数据是什么格式,spark可以读取不同的数据源,包括HDFS (hdfs:// protocol), Amazon S3 (s3n:// protocol), 或本地文件 (file:// protocol)。每一个功能均可返回spark dataframe,且作为tbl类型使用。
整篇以Flights Data数据为例,进行说明:
library(sparklyr)
library(dplyr)
library(nycflights13)
library(ggplot2)
sc <- spark_connect()
flights <- copy_to(sc, flights, "flights")
airlines <- copy_to(sc, airlines, "airlines")
src_tbls(sc)
[1] "airlines" "flights"
2、dplyr 动词操作
例如:
select(flights, year:day, arr_delay, dep_delay)
Source: query [?? x 5]
Database: spark connection master=local app=sparklyr local=TRUE
# S3: tbl_spark
year month day arr_delay dep_delay
<int> <int> <int>
1 2013 1 1 11 2
2 2013 1 1 20 4
3 2013 1 1 33 2
4 2013 1 1 -18 -1
5 2013 1 1 -25 -6
6 2013 1 1 12 -4
7 2013 1 1 19 -5
8 2013 1 1 -14 -3
9 2013 1 1 -8 -3
10 2013 1 1 8 -2
... with more rows
其他操作类似,具体可看dlyr包相应的函数操作。
3、dplyr 的惰性
当使用数据库时,dplyr表现出的惰性:
例如:
c1 <- filter(flights, day == 17, month == 5, carrier %in% c('UA', 'WN', 'AA', 'DL'))
c2 <- select(c1, year, month, day, carrier, dep_delay, air_time, distance)
c3 <- arrange(c2, year, month, day, carrier)
c4 <- mutate(c3, air_time_hours = air_time / 60)
这一系列的操作并未实际接触数据库,直到访问数据(如打印c4)时,dplyr才会向数据库请求结果数据。
c4
Source: query [?? x 8]
Database: spark connection master=local app=sparklyr local=TRUE
# S3: tbl_spark
year month day carrier dep_delay air_time distance air_time_hours
1 2013 5 17 AA -2 294 2248 4.900000
2 2013 5 17 AA -1 146 1096 2.433333
3 2013 5 17 AA -2 185 1372 3.083333
4 2013 5 17 AA -9 186 1389 3.100000
5 2013 5 17 AA 2 147 1096 2.450000
6 2013 5 17 AA -4 114 733 1.900000
7 2013 5 17 AA -7 117 733 1.950000
8 2013 5 17 AA -7 142 1089 2.366667
9 2013 5 17 AA -6 148 1089 2.466667
10 2013 5 17 AA -7 137 944 2.283333
... with more rows
4、管道连接 %>%
可以使用magrittr包中定义的%>%写更清晰的语法:
c4 <- flights %>%
filter(month == 5, day == 17, carrier %in% c('UA', 'WN', 'AA', 'DL')) %>%
select(carrier, dep_delay, air_time, distance) %>%
arrange(carrier) %>%
mutate(air_time_hours = air_time / 60)
5、分组
实现类似SQL中的group by功能:
c4 %>%
group_by(carrier) %>%
summarize(count = n(), mean_dep_delay = mean(dep_delay))
6、将spark数据集加载到R内存中
可以通过collect()函数将spark数据集复制到R的内存中:
carrierhours <- collect(c4)
collect()执行Spark查询,并将结果返回至R作进一步的分析和可视化:
with(carrierhours, pairwise.t.test(air_time, carrier))
ggplot(carrierhours, aes(carrier, air_time_hours)) + geom_boxplot()
另外,可以使用compute()函数将结果作为临时表存储在spark中:
compute(c4, 'carrierhours')
src_tbls(sc)
注:compute()函数是将spark中的结果作为临时表存储在spark中,如果是R内存中的数据,并不能作为临时表存储到spark中。
7、窗口函数
可以使用sample_n()和sample_frac()进行随机抽样:
sample_n(flights, 10)
sample_frac(flights, 0.01)
sql_render()可以比较dplyr语法与它产生的SQL:
bestworst <- flights %>%
group_by(year, month, day) %>%
select(dep_delay) %>%
filter(dep_delay == min(dep_delay) || dep_delay == max(dep_delay))
sql_render(bestworst)
bestworst
SELECT `year`, `month`, `day`, `dep_delay`
FROM (SELECT `year`, `month`, `day`, `dep_delay`, min(`dep_delay`) OVER (PARTITION BY `year`, `month`, `day`) AS `zzz22`, max(`dep_delay`) OVER (PARTITION BY `year`, `month`, `day`) AS `zzz23`
FROM (SELECT `year` AS `year`, `month` AS `month`, `day` AS `day`, `dep_delay` AS `dep_delay`
FROM `flights`) `ihpghnsvzx`) `daiwgkrgiq`
WHERE (`dep_delay` = `zzz22` OR `dep_delay` = `zzz23`)
Source: query [?? x 4]
Database: spark connection master=local app=sparklyr local=TRUE
Groups: year, month, day
# S3: tbl_spark
year month day dep_delay
1 2013 1 5 327
2 2013 1 5 -16
3 2013 6 20 156
4 2013 6 20 -17
5 2013 1 6 -15
6 2013 1 6 202
7 2013 6 21 -15
8 2013 6 21 375
9 2013 1 7 -17
10 2013 1 7 366
... with more rows
8、多个数据集join
很少有数据分析只涉及到单个数据表,在实际中,通常需要灵活的工具将多个表结合起来分析:
inner_join(x, y, by = NULL, copy = FALSE, suffix = c(".x", ".y"), ...)
left_join(x, y, by = NULL, copy = FALSE, suffix = c(".x", ".y"), ...)
right_join(x, y, by = NULL, copy = FALSE, suffix = c(".x", ".y"), ...)
full_join(x, y, by = NULL, copy = FALSE, suffix = c(".x", ".y"), ...)
semi_join(x, y, by = NULL, copy = FALSE, ...)
anti_join(x, y, by = NULL, copy = FALSE, ...)
例如,下面三个语句是等价的:
flights %>% left_join(airlines)
flights %>% left_join(airlines, by = "carrier")
flights %>% left_join(airlines, by = c("carrier", "carrier"))
9、数据保存
通常需要将分析结果进行永久性存储,多数情况下最好的方式是使用spark_write_parquet 函数将结果保存到Parquet 文件:
spark_write_parquet(tbl, "hdfs://hdfs.company.org:9000/hdfs-path/data")
也可以使用spark_read_parquet函数将Parquet文件数据读入spark会话中:
tbl <- spark_read_parquet(sc, "data", "hdfs://hdfs.company.org:9000/hdfs-path/data")
同样的,也可以使用spark_write_csv和spark_write_json函数写入csv文件和json文件中。