草庐IT

R语言-data.table包用来加速大型数据集的加载和运算

倪桦 2023-09-28 原文


R语言具有较强的数据分析能力,但是对于数据处理,尤其是面对较大数据量时,就有很多的不足之处,为了解决处理较大数据集的问题,R中涌现了一系列数据处理的包,data.table包就是其中之一。

R语言data.table包是自带包data.frame的升级版,用于数据框格式数据的处理,最大的特点是。它内部处理的步骤进行了程序上的优化,使用多线程,还有很多C编写的函数,大大加快数据运行速度。尤其当对一两百万甚至更大数据集进行修改或运算时,由于data.table直接对数据本身做运算,不创建副本,因此相较于基本的data.frame格式,data.table在面对大型数据集时,进行聚合排序以及分组运算的性能非常高 !


data.table和data.frame的主要格式区别是data.table格式没有行名,但可以通过设置键来指定索引列,根据索引列的值进行数据索引。

本文主要整理了下data.table对象的一些常用操作方法

1、 data.table的一般语法格式

data.table数据框结构处理语法 DT[ i , j , by]

  • i 决定显示的行,可以是整型,可以是字符,可以是表达式,
  • j 是对数据框进行求值,决定显示的列,
  • by对数据进行指定分组,除了by ,也可以添加其它的一系列参数:keyby,with,nomatch,mult,rollollends,which,.SDcols,on等

2、读写文件

读取文件的4种便捷操作:
  • ① - nrows参数指定读取多少行
    fread("fileName", sep="\t",nrows = 10)
  • ② - select参数选择要导入的列或drop参数进行反向选择
    fread("fileName", sep="\t",select = c("column_1", "column_2", 6 ))
    fread("fileName", sep="\t",drop = c("column_3", "column_4", 5 ))
  • ③- *colClasses参数在加载文件时完成列属性指定
    fread("fileName", sep="\t", colClasses = c("column_1" = "numeric"))
  • ④ - cmd参数配合使用Linux命令读取zip文件
    fread(cmd = 'unzip -cq fileName.zip' ,sep="\t").
写出文件:

fwrite(out,"fileName",col.names=T,row.names=F,sep="\t",quote=F)

3、数据框对象转换

as.data.table和setDT也可用于转换list和data.frame为data.table对象,不同的是前者会完全复制原对象,然后进行转换,而setDT方法以传地址的方式直接修改原对象,不拷贝直接操作原数据集,因此前者更加的耗时和耗内存。
dt <- setDT(df,keep.rownames = T, key = "rn")

  • keep.rownames 参数保留原data.frame的行名,默认新建一列"rn"存放原data.frame的行名
  • key 参数设置dt对象的索引列,列的值可以重复。键值设置还可以通过 setkey(df,"rn")

4、对象操作记录

(1) 数据集的行记录过滤
DT = data.table(x=rep(c( "b", "a", "c" ),each=3), y=c(1,3,6), v=1:9)
DT[2] #取第二行
DT[2:3] #取第二到第三行
DT[order(x)] #将DT按照X列排序,简化操作,另外排序也可以setkey(DT,x),出来的DT就已经是按照x列排序的了。用haskey(DT)判断DT是否已经设置了key,可以设置多个列作为key
DT[y 2] # DT$y 2的行
DT[!2:4] #除了2到4行剩余的行
DT[ "a" ,on= "x" ] #on 参数,在x列取出值为"a"的行
DT[.( "a" ), on= "x" ] #和上面一样.()有类似与c()的作用
DT[ "a" , on=.( x )] #和上面一样
DT[ x == "a" ] # 和上面一样,和使用on一样,都是使用二分查找法,所以它们速度比用data.frame的快。
DT[x! = "b" | y != 3 ] #x列不等于 b 或者y列不等于3的行
DT[.( "b" , 3), on=.(x, v)] #取DT的x,v列上x= b ,v=3的行
(2) 数据框的求值操作

数据运算包括输出sum,max,min,tail等基本函数的计算结果,还可以用n输出第n列,.N(总列数,直接在j输入.N取最后一列),:=(直接在data.table上新建列),.SD(SubDadaColums)输出子集,.SD[n]输出子集的第n列。

DT = data.table(x=rep(c( "b", "a", "c" ),each=3), y=c(1,3,6), v=1:9)
DT[,y] #返回y列,矢量
DT[,.(y)] #返回y列,返回data.table
DT[, sum(y)] #对y列求和
DT[, .(sv=sum(v))] #对y列求和,输出sv列,列中的内容就是sum(v)
DT[, .(sum(y)), by=x] # 对x列进行分组后对各分组y列求总和
DT[, sum(y), keyby=x] #对x列进行分组后对各分组y列求和,并且结果按照x排序
DT[, sum(y), by=x][order(x)] #和上面一样,采取data.table的链接符合表达式
DT[v==1, sum(y), by=x] #对v列进行分组后,取各组中v==1的行出来,各组分别对定义的行中的y求和
DT[, .N, by=x] #用by对DT 用x分组后,取每个分组的总行数
DT[, .SD, .SDcols=x:y] #用.SDcols 定义SubDadaColums(子列数据),这里取出x到y之间的列作为子集,然后.SD 输出所有子集
DT[, .SD[1], by = x] #抽提x列分组后每个子集的第一行
DT[, .SD[.N], by = x] #抽提x列分组后每个子集的最后一行
DT[2:5, cat(y,"\n" )] #直接在j 用cat函数,输出2到5列的y值
DT[, plot(a,b), by=x] #直接在j用plot函数画图,对于每个x的分组画一张图
DT[, m:=mean(v), by=x] #对DT按x列分组,直接在DT上再添加一列m,m的内容是mean(v),直接修改并且不输出到屏幕上
DT[, m:=mean(v), by=x] [] #加[]将结果输出到屏幕上
DT[,c( m , n ):=list(mean(v),min(v)), by=x][] # 按x分组后同时添加m,n 两列,内容是分别是mean(v)和min(v),并且输出到屏幕
DT[,.(seq = min(y):max(v)), by=x] #输出seq列,内容是min(a)到max(b)
DT[, c(.(y=max(y)), lapply(.SD, min)), by=x, .SDcols=y:v] #对DT取y:v之间的列,按x分组,输出max(y),对y到v之间的列
(3)删除一列

DT[,x := NULL]

(4)列属性转换

DT[,b := as.integer(y)]
其它有如as.integer(), as.numeric(),as.character(), as.Date()等函数

(5)根据多列的值进行去重

unique(DT, by = c("x","y"))

(6)根据列重排序

setorder(DT, x, -y) #x列升序,y列降序(-)

(7)配合使用lapply示例

对DT根据x列进行分组,子集保留"v", "y"两列,对每个自己的这两列求取均值:
DT[, lapply(.SD, mean), .SDcols = c("v", "y"),by = x ]

(8)分组计数

DT[, c := .N, by = x]

(9) 为特定的单元格赋值

将DT第五行的"y", "v"两列的值替换第二行"y", "v"的值
DT[2, c("y", "v") := as.list(DT[5, c(y, v)])]
直接修改第一行x列的单元格值为MMM
DT[1,x := "MMM"]

(10) 数据框链接

内联接,nomatch=0表示不返回不匹配的行,nomatch=NA表示以NA返回不匹配的值
DT[X, on= .("x","y") , nomatch=0]

(11) 内容搜索返回行号,设置参数which =NA

DT["a",on = .(x), which = TRUE ] #在x列匹配值为"a"的记录的行号

官方文档:extension://bfdogplmndidlpjfhoijckpakkdjkkil/pdf/viewer.html?file=file%3A%2F%2F%2FC%3A%2FUsers%2F13321%2FAppData%2FLocal%2FTemp%2FMicrosoftEdgeDownloads%2F7298ded2-e89a-4543-a6e5-0afd0e7e87e3%2Fdatatable.pdf
Rdatatable/data.table: R's data.table package extends data.frame: (github.com)
R语言数据分析利器data.table包 —— 数据框结构处理精讲-汗血宝马 (caotama.com)

有关R语言-data.table包用来加速大型数据集的加载和运算的更多相关文章

  1. ruby - 如何将脚本文件的末尾读取为数据文件(Perl 或任何其他语言) - 2

    我正在寻找执行以下操作的正确语法(在Perl、Shell或Ruby中):#variabletoaccessthedatalinesappendedasafileEND_OF_SCRIPT_MARKERrawdatastartshereanditcontinues. 最佳答案 Perl用__DATA__做这个:#!/usr/bin/perlusestrict;usewarnings;while(){print;}__DATA__Texttoprintgoeshere 关于ruby-如何将脚

  2. ruby - 解析 RDFa、微数据等的最佳方式是什么,使用统一的模式/词汇(例如 schema.org)存储和显示信息 - 2

    我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i

  3. ruby - 如何在续集中重新加载表模式? - 2

    鉴于我有以下迁移:Sequel.migrationdoupdoalter_table:usersdoadd_column:is_admin,:default=>falseend#SequelrunsaDESCRIBEtablestatement,whenthemodelisloaded.#Atthispoint,itdoesnotknowthatusershaveais_adminflag.#Soitfails.@user=User.find(:email=>"admin@fancy-startup.example")@user.is_admin=true@user.save!ende

  4. ruby - RuntimeError(自动加载常量 Apps 多线程时检测到循环依赖 - 2

    我收到这个错误:RuntimeError(自动加载常量Apps时检测到循环依赖当我使用多线程时。下面是我的代码。为什么会这样?我尝试多线程的原因是因为我正在编写一个HTML抓取应用程序。对Nokogiri::HTML(open())的调用是一个同步阻塞调用,需要1秒才能返回,我有100,000多个页面要访问,所以我试图运行多个线程来解决这个问题。有更好的方法吗?classToolsController0)app.website=array.join(',')putsapp.websiteelseapp.website="NONE"endapp.saveapps=Apps.order("

  5. ruby - Ruby 有 `Pair` 数据类型吗? - 2

    有时我需要处理键/值数据。我不喜欢使用数组,因为它们在大小上没有限制(很容易不小心添加超过2个项目,而且您最终需要稍后验证大小)。此外,0和1的索引变成了魔数(MagicNumber),并且在传达含义方面做得很差(“当我说0时,我的意思是head...”)。散列也不合适,因为可能会不小心添加额外的条目。我写了下面的类来解决这个问题:classPairattr_accessor:head,:taildefinitialize(h,t)@head,@tail=h,tendend它工作得很好并且解决了问题,但我很想知道:Ruby标准库是否已经带有这样一个类? 最佳

  6. ruby - 寻找通过阅读代码确定编程语言的ruby gem? - 2

    几个月前,我读了一篇关于ruby​​gem的博客文章,它可以通过阅读代码本身来确定编程语言。对于我的生活,我不记得博客或gem的名称。谷歌搜索“ruby编程语言猜测”及其变体也无济于事。有人碰巧知道相关gem的名称吗? 最佳答案 是这个吗:http://github.com/chrislo/sourceclassifier/tree/master 关于ruby-寻找通过阅读代码确定编程语言的rubygem?,我们在StackOverflow上找到一个类似的问题:

  7. ruby-on-rails - 更好的替代方法 try( :output). try( :data). try( :name)? - 2

    “输出”是一个序列化的OpenStruct。定义标题try(:output).try(:data).try(:title)结束什么会更好?:) 最佳答案 或者只是这样:deftitleoutput.data.titlerescuenilend 关于ruby-on-rails-更好的替代方法try(:output).try(:data).try(:name)?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.c

  8. ruby-on-rails - Prawn PDF : I need to generate nested tables - 2

    我需要一个表,其中行实际上是2行表,一个嵌套表是..我怎样才能在Prawn中做到这一点?也许我需要延期..但哪一个? 最佳答案 现在支持子表:Prawn::Document.generate("subtable.pdf")do|pdf|subtable=pdf.make_table([["sub"],["table"]])pdf.table([[subtable,"original"]])end 关于ruby-on-rails-PrawnPDF:Ineedtogeneratenested

  9. ruby-on-rails - 使用 config.threadsafe 时从 lib/加载模块/类的正确方法是什么!选项? - 2

    我一直致力于让我们的Rails2.3.8应用程序在JRuby下正确运行。一切正常,直到我启用config.threadsafe!以实现JRuby提供的并发性。这导致lib/中的模块和类不再自动加载。使用config.threadsafe!启用:$rubyscript/runner-eproduction'pSim::Sim200Provisioner'/Users/amchale/.rvm/gems/jruby-1.5.1@web-services/gems/activesupport-2.3.8/lib/active_support/dependencies.rb:105:in`co

  10. ruby - 我如何添加二进制数据来遏制 POST - 2

    我正在尝试使用Curbgem执行以下POST以解析云curl-XPOST\-H"X-Parse-Application-Id:PARSE_APP_ID"\-H"X-Parse-REST-API-Key:PARSE_API_KEY"\-H"Content-Type:image/jpeg"\--data-binary'@myPicture.jpg'\https://api.parse.com/1/files/pic.jpg用这个:curl=Curl::Easy.new("https://api.parse.com/1/files/lion.jpg")curl.multipart_form_

随机推荐