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

讨论 BenjaminC
Lv2 初级炼丹师
发布在 Pandas   1646   0
讨论 BenjaminC   1646   0

    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('/home/kesci/input/rlang_dt2138/BostonHousing.csv')
    head(DT)

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

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

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

    # fread 函数的 select 参数指定读取的列名称
    DT <- fread('/home/kesci/input/rlang_dt2138/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] 语法
    版权声明:作者保留权利,不代表意本站立场。如需转载请联系本站以及作者。

    参与讨论

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

    EditorJs 编辑器

    沙发,很寂寞~
    反馈
    to-top--btn