vlambda博客
学习文章列表

R语言中的Pandas:50题搞定 data.table

之前和鲸社区的作者创作了有关R语言数据分析相关的项目《R语言数据处理120题》,有热心网友表示data.frame不如data.table给力

R语言中的Pandas:50题搞定 data.table

R语言中的Pandas:50题搞定 data.table

行了行了,知道了,这就安排!

我们邀请了和鲸社区创作者@黄凯 老师,对照着国外某网站的教程《101 R data.table Exercises,进行了翻译整理以及二次创作,用50道题的篇幅,教大家data.table 的各种技巧。项目共分为:基础问题、缺失值处理、选择数据与分组聚合计算、综合性问题、data.table 数据分析案例 ,5个部分。

R语言中的Pandas:50题搞定 data.table


以下正文




R语言:50题搞定 data.table

 简介 

data.table 是 R 语言中用于处理表格数据的包,相当于 Python 语言的 pandas,是学习 R 语言数据分析与挖掘必备工具。接下来我们用 50 道题学习data.table 的各种技巧。

尽管 data.table 提供了与 data.frame 稍有不同的语法,但是非常简单好用,相对于 data.frame 速度极快,一旦你学会了 data.table,一般的就不太想回到 data.frame 了。

 0.基础问题 

1.新建 data.table

# 使用 data.table 直接创建
DT = data.table(
  a = 1:6,
  b = 7:12,
  c = 13:18
)
DT

2.如何从 list 创建一个 dt

# 如何从以下的 list 创建一个 dt
list_1 <- c("a","b","c","d")
list_2 <- c("1","2","3","4")
list_3 <- c("aa","bb","cc","dd")

# 答案
DT <- data.table(V1= list_1, V2 =list_2, V3 = list_3 )
DT

3.如何从 data.frame 转换为 data.table

DF <- read.csv('test.csv')
print ( class(DF))

# 用 setDT 函数转换为 data.table
setDT(DF)
print (class(DF))

4.如何从data.table 转换为 data.frame

DT = data.table(
  a = 1:6,
  b = 7:12,
  c = 13:18
)
print(class(DT))

# 用 setDF 函数转换为 data.frame
setDF(DT)
print(class(DT))

5.如何导入 csv 文件

# 用 fread : fast read 函数
DT <- fread('BostonHousing.csv')
head(DT)

6.如何只从csv 文件导入10行数据

# fread 函数的 nrows 参数指定读取行数
DT <- fread('BostonHousing.csv', nrows = 10)
DT

7.如何只从 csv 文件导入指定的数据列

# fread 函数的 select 参数指定读取的列名称
DT <- fread('BostonHousing.csv', select = c('crim''medv'))
head(DT)

8.如何获取 data.table 的基本信息:几行、几列、数据类型、汇总信息等等

DT <- fread('BostonHousing.csv')

# 几行、几列
print(nrow(DT))
print(ncol(DT))

# 数据类型
print(sapply(DT, class))

# 汇总信息
summary(DT)

9.如何重命名数据列

DT <- fread('BostonHousing.csv')

# setnames 方法重命名数据列
setnames(DT, old = "medv", new = "价格")
head(DT)


1.缺失值处理 

10.如何判断 data.table 有缺失值

DT <- fread('BostonHousing.csv')

# 用 anyNA 判断
anyNA(DT)

11.如何查看哪些数据是缺失的

# Cars93 数据集中第16行数据有缺失值存在
DT <- fread('Cars93.csv' )

#  Luggage.room 是 na
print(is.na(DT[16]))

12.如何获取缺失值所在的位置(行、列值)

DT <- fread('Cars93.csv')
output <- c()  # 输出数组

# 遍历数据集
for(i in 1:nrow(DT)){
  for(j in 1:ncol(DT)){
    # 获取当前元素
    curr_value <- DT[i, j,with=F][[1]]
    if(is.na(curr_value)){
      # 如果是缺失值,将其位置放入 output 中
      position <- paste0('(', paste(i, j, sep=', '), ')')
      output   <- c(output, position)
    }
  }
}

output

13.如何统计每一列的缺失值

DT <- fread('Cars93.csv')
# summary 函数中有统计
# 因为已经知道Rear.seat.room  , Luggage.room 这两列有缺失值,因此就只打印这两列的 summary 信息
summary(DT[, .(Rear.seat.room  , Luggage.room)])

14.如何替换缺失值为 0

DT <- fread('Cars93.csv')

print(summary(DT[, .(Rear.seat.room  , Luggage.room)]))
# 直接赋值
DT[ is.na(DT)] <- 0
print("对缺失值赋值后,可以看到这两列数据没有缺失值了")
print(summary(DT[, .(Rear.seat.room  , Luggage.room)]))

15.如何替换缺失值为均值

DT <- fread('Cars93.csv')

replace_with_mean <- function(x){ifelse(is.na(x),mean(x, na.rm = TRUE),x)}
output <- DT[,lapply(.SD, replace_with_mean)]
summary(output)

2.选择数据与分组聚合计算

16.如何选择一列数据并返回 list

DT <- fread('BostonHousing.csv')

# 使用 [i,j, by] 语法
# i: 相当于 SQL 的 where
# j: 相当于 SQL 的 select
# by: 相当于 SQL 的 group by
class(DT[, medv])

## 方法二

# 如果不知道列名称的话,可以用索引数字来选择指定的列,例如 第一列数据
head(DT[, 1])

17.如何选择一列数据并返回 data.table

DT <- fread('BostonHousing.csv')

# 用 list(列名称),这样返回的是 data.table 类型
class(DT[, list(medv)])
# .() 是 list() 的简写
class(DT[, .(medv)])

18.如何选择多列数据

# 用 .() 选择多列数据
head(DT[, .(crim, medv) ])

## 方法二
# 用数字列表选择多个列
head(DT[, 1:3])

19.如何选择列的同时改变列名称

DT <- fread('BostonHousing.csv')

# 使用赋值语法
head(DT[, .("价格" = medv, "犯罪率"= crim) ])

20.如何删除指定的列

DT <- fread('BostonHousing.csv')

# 将需要删除的列名称放入一个数组中,前面加上 ! 就表示不需要指定的列
# 这里需要用字符串来指定列名
head( DT[, ! c("crim""zn""indus")])

21.如何按照指定的列排序

DT <- fread('BostonHousing.csv')

# 用 order 函数
head(DT[ order(medv)])

# 倒排 
head(DT[ order(-medv)])

# 多个列排序
head(DT[ order(-medv, crim)])

# 排序,并选择指定的列
head(DT[ order(-medv, crim), .(medv, crim)])

22.如何筛选数据

DT <- fread('BostonHousing.csv')

# 类似于 SQL 的判断语法
head( DT[ medv == 50 & crim > 0.5  ])

# 加上排序
head( DT[ medv == 50 & crim > 0.5  ][order(crim)])

23.如何选择指定条件的数据并进行聚合计算(均值、最大值等)

DT <- fread('BostonHousing.csv')

# 筛选 medv 大于 30 的数据, 并计算 age 列的均值, tax 最大值
head( DT[medv > 30, .("Age 均值"= mean(age), "Tax 最大值"= max(tax) ) ])

24.如何分组计算唯一值 以汽车数据集为例,按 Manufacturer(汽车制造商) 分组,计算 Model 有多少个唯一值

DT <- fread('Cars93.csv')

# 用 unique 函数, 结合 list 来获取
DT[, .('Models'= .(list(unique(Model))), 'Length'= lengths( list(unique(Model))) ) ,Manufacturer ][order(Length,decreasing=T)]

25.如何进行分组聚合计算1 以汽车数据集为例, 先按 Manufacturer(汽车制造商) 分组,在统计每个制造商生产的数量

DT <- fread('Cars93.csv')

# 按照 Manufacturer 分组
# 用 .N 进行计数
head( DT[, .N ,  Manufacturer] )

26.如何进行分组聚合计算2 以汽车数据集为例, 先按 Manufacturer(汽车制造商), Type (类型) 分组,在计算价格的均值,最大值,最小值

head( DT[, .( mean(Price), max(Price), min(Price), .N) , .( Manufacturer, Type) ] )

27.如何进行分组聚合计算3 以汽车数据集为例, 先按 Manufacturer(汽车制造商), Type (类型) 分组,再计算价格的均值。对结果按照 Manufacturer(汽车制造商), Type (类型) 排序

# 对返回结果在使用 order 进行排序 
head( DT[, .( mean(Price), max(Price), min(Price), .N) , .( Manufacturer, Type) ][order(Manufacturer, Type)] )

## 方法二
# 用 keyby 参数实现同样效果
head( DT[, .( mean(Price), max(Price), min(Price), .N) , keyby=.( Manufacturer, Type) ] )

28.如何选择所有数值类型的列

DT <- fread('Cars93.csv')
head(DT[, .SD, .SDcols = which(sapply(DT, is.numeric))])

29.如何按 Manufacturer(汽车制造商)分组计算所有数值类型的均值

DT <- fread('Cars93.csv')
# 获得所有数值类型的列: .SDcols = which(sapply(DT, is.numeric))
# 对数值列计算均值:lapply(.SD, mean)
# 按 Manufacturer 分组:by = Manufacturer
head(DT[, lapply(.SD, mean), .SDcols = which(sapply(DT, is.numeric)), by = Manufacturer])


 3.综合性问题 

30.如何获取每个 Manufacturer 的第一行数据

DT <- fread('Cars93.csv')

# 获取 一行数据:head(.SD, 1)
# 按  Manufacturer 分组并排序:keyby = Manufacturer
head(  DT[, head(.SD, 1), keyby = Manufacturer])

31.如何设置数据列为主键列

DT <- fread('Cars93.csv')

# 设置 Type 为主键列
setkey(DT, Type)

32.如何获取 Type 为 Small 的所有数据

DT <- fread('Cars93.csv')

# 用 == 判断
head( DT [ Type == 'Small'] )

## 方法二
# 首先将 Type 设为主键
setkey(DT, Type)

# 用主键进行判断
head(DT['Small'])

33.如何获得 Type 为 'Midsize', 'Small' 的数据

DT <- fread('Cars93.csv')
# 首先将 Type 设为主键
setkey(DT, Type)

# 多个匹配
head(DT[c('Midsize''Small')], 2)
# 用 tail 看一下 Small 类型也被匹配了
tail(DT[c('Midsize''Small')], 2)

34.如何按 Manufacturer 分组后计算 Price 的方差

DT <- fread('Cars93.csv')

# 按 Manufacturer 分组
# 用 sd 方法计算 Price 的方差
head(DT[, sd(Price), Manufacturer])

35.如何获取 Type= Small, 按 Manufacturer 分组,计算 Price 的均值

DT <- fread('Cars93.csv')

# i: 判断语句
# j: 计算 Price 均值
# by: 按Manufacturer分组 
DT[Type=='Small', mean(Price) , by= Manufacturer]

36.如何得到 Price 最大值所在的行

DT <- fread('Cars93.csv')

# 使用 tail 即可
tail(DT[order(Price)], 1)

37.如何得到Price 第5个最大值所在的行

DT <- fread('Cars93.csv')

# 灵活使用 head/tail
head(tail(DT[order(Price)], 5), 1)

38.如何计算数值列之间的 correlation score

DT <- fread('Cars93.csv')

# 用 cor 函数计算 DT 中的数值列
cor( DT[, .SD, .SDcols = which(sapply(DT, is.numeric))])

39.如何 normalize 指定的列、所有数值列

DT <- fread('Cars93.csv')

# normalize 所有数值列
head(DT[, lapply(.SD, scale), .SDcols = which(sapply(DT, is.numeric))])

# normalize 指定的列
head(DT[, scale(.SD), .SDcols= c('Price''RPM')] )


 4.data.table 数据分析案例 

40.导入并查看数据

flights <- fread('flights14.csv')
head(flights)

41.获得所有六月份从 JFK 出发的航班数据

head( flights[origin== "JFK" & month == 6] )

42.选择 arr_delay 和 dep_delay 并重命名为 到达延误 和 起飞延误

head(flights[, .('到达延误'= arr_delay, '起飞延误'= dep_delay)])

43.有多少航班的总延误时间 < 0

flights[, sum( (arr_delay+dep_delay)<0 )]

44.计算6月份从 JFK 起飞的航班的起飞延误和到达延误均值

flights[origin== "JFK" & month == 6, .('到达延误'= mean(arr_delay), '起飞延误'= mean(dep_delay))]

45.按起飞机场分组,计算航班数

flights[, .N, origin]

46.哪个机场最繁忙?哪个月份机场最繁忙?

# 最繁忙的机场
flights[, .N, origin][order(N, decreasing=T)][1]

# 最繁忙的月份
flights[, .N, month][order(N, decreasing=T)][1]

# 最繁忙的月份+机场组合前三名
flights[, .N, .(month, origin)][order(N, decreasing=T)][1:3]

47.按起飞、降落机场分组,获取 AA 航空公司的航班数

head( flights[carrier=="AA", .N, .(origin, dest) ] )

48.获取按起飞、降落延误分组的航班数

flights[, .N, .(dep_delay >0, arr_delay>0)]

49.按起飞机场、月份分组,获取 AA 航空公司的起飞、降落平均延误时间

flights[ carrier=="AA",
    lapply(.SD, mean) ,
    by = .(origin, month),
    .SDcols = c("dep_delay""arr_delay")
]

50.6月份哪个机场起飞延误情况最为严重?

flights[dep_delay>0
    ][, mean(dep_delay), .(carrier, month)
    ][order(V1, decreasing=T)][1]



 总结 


  • data.table 是 R 语言用于处理数据的最佳工具

  • 掌握 data.table[i,j,by] 语法



 附录 

英文原文链接:

https://www.machinelearningplus.com/data-manipulation/101-r-data-table-exercises/


R语言数据处理120题:

https://www.kesci.com/home/project/5f14ff3094d484002d28bbcb


※ 点击 阅读原文 可跳转至项目


R语言中的Pandas:50题搞定 data.table


数据集 /   /    /   /   /   /  /

教程 /   / h /   /   /   /   /   /   /     /  /  /   /  /  /  /

项目 /   /   /   /   /   /  /  /  /

比赛 /   /  /  /   /