专栏首页优雅R「Workshop」第四十二期 R文件读写

「Workshop」第四十二期 R文件读写

rio package

rio是一个比较简单,但是又非常强大的一个数据读写包,这个包的特点是:根据文件的拓展名推断文件的类型,然后调用不同的包来读写数据,目前支持的文件类型

主要使用的函数有:

  • importimport_list
  • exportexport_list
  • convert

import

import函数的用法:

import(file, format, setclass, which, ...)
  • file指定文件名
  • format 一般是根据文件名来推断文件类型,但是也可以通过这个参数来指定文件类型
  • setclass 指定读入数据后返回的数据类型,默认是data.frame,可以更改为"tbl_df","tbl","tibble","data.table"
  • which 当我们需要从含有多个数据对象的文件中读取数据时可以指定这个参数;比如file是一个压缩的文件夹,可以使用该参数来指定需要读取的文件;如果是一个excel表格(含有多个子表格),可以使用which指定读取的表格;如果是一个Rdata文件也可以指定需要读取的对象

当我们在一个文件夹下有多个文件,可以使用import_list函数来一次性读入:

list.files("./files_list/")
#[1] "ACC_simulation.rds"  "BLCA_simulation.rds" "BRCA_simulation.rds"
dt <- import_list(file =paste0("./files_list/",dir("files_list/")),rbind = T)

export

export函数的用法为:

export(x, file, format, ...)
  • x 数据框或者矩阵
  • file 保存的文件名
  • format 保存的文件格式(文件拓展名);fileformat至少要指定一个

也可以使用export将多个对象输出到一个文件中(excel和Rdata):

##export
export(iris,file = "iris.csv")
# export to sheets of an Excel workbook
export(list(mtcars = mtcars, iris = iris), "multi.xlsx")
# export to an .Rdata file
## as a named list
export(list(mtcars = mtcars, iris = iris), "multi.rdata")
## as a character vector
export(c("mtcars", "iris"), "multi2.rdata")

export_list可以将多个对象输出为多个文件:

export_list(list(mtcars = mtcars, iris = iris), "%s.tsv")

convert

convert函数是importexport函数的包装,可以直接将一种格式的文件转化成另一种格式的文件

convert(in_file = "iris.csv",out_file = "iris.tsv")

readr package

readr包主要有7个函数用来进行数据的读入:

  • read_csv(): comma separated (CSV) files
  • read_tsv(): tab separated files
  • read_delim(): general delimited files
  • read_fwf(): fixed width files
  • read_table(): tabular files where columns are separated by white-space.
  • read_log(): web log files

base Rread.*函数相比,readr包的read_*函数的特点有:

  • 更快
  • 读入的数据类型是tibbles,不会将字符变量转化为因子;可以自动的解析常见的时间格式
  • base R在读取数据时可能会继承一些操作系统的行为或者环境变量,使得代码的复用性降低

5-1-1

readr将文件解析成tibble分成3个步骤:

  • 文件被解析成字符串矩阵
  • 决定每列的数据类型
  • 将每列的字符串按照特定的数据类型进行解析

向量解析

向量解析使用parse_*函数,将字符向量转化为特定类型的向量

parse_integer(c("1", "2", "3"))
#> [1] 1 2 3
parse_double(c("1.56", "2.34", "3.56"))
#> [1] 1.56 2.34 3.56
parse_logical(c("true", "false"))
#> [1]  TRUE FALSE

readr默认.作为小数点,,作为分节号(group marker),可以使用locale()来更改:

parse_double(c("1,56", "2,34", "356"),locale=locale(decimal_mark = ","))

使用parse_number可以更灵活的解析字符到数字:

parse_number(c("0%", "10%", "150%"))
#> [1]   0  10 150
parse_number(c("$1,234.5", "$12.45"))
#> [1] 1234.50   12.45

readr也支持日期,时间数据的解析,有3个函数:

  • parse_datetime() ISO8601
  • parse_date()
  • parse_time()
parse_datetime("2010-10-01T2010")
#> [1] "2010-10-01 20:10:00 UTC"
# If time is omitted, it will be set to midnight
parse_datetime("20101010")
#> [1] "2010-10-10 UTC"

parse_date("2010-10-01")
#> [1] "2010-10-01"

library(hms)
parse_time("01:10 am")
#> 01:10:00
parse_time("20:10:01")
#> 20:10:01

列类型判断

readr使用启发式的方法来猜测每一列的数据类型,使用的函数是guess_parser:

guess_parser(c("a", "b", "c"))
#> [1] "character"
guess_parser(c("1", "2", "3"))
#> [1] "double"
guess_parser(c("1,000", "2,000", "3,000"))
#> [1] "number"
guess_parser(c("2001/10/10"))
#> [1] "date"

在读入文件的时候可以使用col_type来人为指定列的类型

可以通过spec_**函数来查看数据读入过程中的列类型判断:

x <- spec_csv(readr_example("challenge.csv"))
#> 
#> ── Column specification ────────────────────────────────────────────────────────
#> cols(
#>   x = col_double(),
#>   y = col_logical()
#> )

数据解析

当使用readr的7个函数读入数据时,这些函数会先读入字符矩阵,然后调用spec_*函数来决定每列的数据类型,最后根据这个类型来解析每一列:

df2 <- read_csv("iris.csv")
# Parsed with column specification:
#   cols(
#     Sepal.Length = col_double(),
#     Sepal.Width = col_double(),
#     Petal.Length = col_double(),
#     Petal.Width = col_double(),
#     Species = col_character()
#   )

可能存在的问题

readr猜列的数据类型时是先读入前1000行,然后根据这1000行来决定列的数据类型:

challenge <- read_csv(readr_example("challenge.csv"))
#> 
#> ── Column specification ────────────────────────────────────────────────────────
#> cols(
#>   x = col_double(),
#>   y = col_logical()
#> )
#> Warning: 1000 parsing failures.
#>  row col           expected     actual                                                           file
#> 1001   y 1/0/T/F/TRUE/FALSE 2015-01-16 '/Users/runner/work/_temp/Library/readr/extdata/challenge.csv'
#> 1002   y 1/0/T/F/TRUE/FALSE 2018-05-18 '/Users/runner/work/_temp/Library/readr/extdata/challenge.csv'
#> 1003   y 1/0/T/F/TRUE/FALSE 2015-09-05 '/Users/runner/work/_temp/Library/readr/extdata/challenge.csv'
#> 1004   y 1/0/T/F/TRUE/FALSE 2012-11-28 '/Users/runner/work/_temp/Library/readr/extdata/challenge.csv'
#> 1005   y 1/0/T/F/TRUE/FALSE 2020-01-13 '/Users/runner/work/_temp/Library/readr/extdata/challenge.csv'
#> .... ... .................. .......... ..............................................................
#> See problems(...) for more details.

###使用problem查看问题
problems(challenge)
#> # A tibble: 1,000 x 5
#>     row col   expected        actual   file                                     
#>   <int> <chr> <chr>           <chr>    <chr>                                    
#> 1  1001 y     1/0/T/F/TRUE/F… 2015-01… '/Users/runner/work/_temp/Library/readr/…
#> 2  1002 y     1/0/T/F/TRUE/F… 2018-05… '/Users/runner/work/_temp/Library/readr/…
#> 3  1003 y     1/0/T/F/TRUE/F… 2015-09… '/Users/runner/work/_temp/Library/readr/…
#> 4  1004 y     1/0/T/F/TRUE/F… 2012-11… '/Users/runner/work/_temp/Library/readr/…
#> 5  1005 y     1/0/T/F/TRUE/F… 2020-01… '/Users/runner/work/_temp/Library/readr/…
#> 6  1006 y     1/0/T/F/TRUE/F… 2016-04… '/Users/runner/work/_temp/Library/readr/…
#> # … with 994 more rows

这个challenge数据集的第二列前1000行是NA,所以readr认为它是逻辑值,这个时候我们可以指定列的类型(col_types)或者增多猜所依据的行数(guess_max):

challenge <- read_csv(
  readr_example("challenge.csv"), 
  col_types = cols(
    x = col_double(),
    y = col_date()
  )
)

challenge2 <- read_csv(readr_example("challenge.csv"), guess_max = 1001)
#> 
#> ── Column specification ────────────────────────────────────────────────────────
#> cols(
#>   x = col_double(),
#>   y = col_date(format = "")
#> )

也可以将数据全部以字符形式读入,然后再使用type_convert进行转化(这个时候如果没有指定列的类型,是根据所有的行进行推测的):

challenge2 <- read_csv(readr_example("challenge.csv"), 
  col_types = cols(.default = col_character())
)
type_convert(challenge3) -> a
# Parsed with column specification:
#   cols(
#     x = col_double(),
#     y = col_date(format = "")
#   )

数据输出

readr使用write_*函数来输出文件

当使用write_csv或者write_tsv等函数时,指定的列的类型会丢失(再次读入时还需要指定):

write_csv(challenge, "challenge-2.csv")
read_csv("challenge-2.csv")
# Parsed with column specification:
#   cols(
#     x = col_double(),
#     y = col_logical()
#   )
# Warning: 1000 parsing failures.
# row col           expected     actual              file
# 1001   y 1/0/T/F/TRUE/FALSE 2015-01-16 'challenge-2.csv'
# 1002   y 1/0/T/F/TRUE/FALSE 2018-05-18 'challenge-2.csv'
# 1003   y 1/0/T/F/TRUE/FALSE 2015-09-05 'challenge-2.csv'
# 1004   y 1/0/T/F/TRUE/FALSE 2012-11-28 'challenge-2.csv'
# 1005   y 1/0/T/F/TRUE/FALSE 2020-01-13 'challenge-2.csv'
# .... ... .................. .......... .................
# See problems(...) for more details.
# 
# # A tibble: 2,000 x 2
# x y    
# <dbl> <lgl>
#   1   404 NA   
# 2  4172 NA   
# 3  3004 NA   
# 4   787 NA   
# 5    37 NA   
# 6  2332 NA   
# 7  2489 NA   
# 8  1449 NA   
# 9  3665 NA   
# 10  3863 NA   
# # ... with 1,990 more rows

把文件保存为rds或者feather文件就不会出现这种问题:

write_rds(challenge, "challenge.rds")
read_rds("challenge.rds")
#> # A tibble: 2,000 x 2
#>       x y         
#>   <dbl> <date>    
#> 1   404 NA        
#> 2  4172 NA        
#> 3  3004 NA        
#> 4   787 NA        
#> 5    37 NA        
#> 6  2332 NA        
#> # … with 1,994 more rows

##feather可以被python使用
library(feather)
write_feather(challenge, "challenge.feather")
read_feather("challenge.feather")
#> # A tibble: 2,000 x 2
#>       x      y
#>   <dbl> <date>
#> 1   404   <NA>
#> 2  4172   <NA>
#> 3  3004   <NA>
#> 4   787   <NA>
#> 5    37   <NA>
#> 6  2332   <NA>
#> # ... with 1,994 more rows
##python input
import feather
path = 'data/co2.feather'
df_co2_feather = feather.read_dataframe(path)

本文分享自微信公众号 - 优雅R(elegant-r),作者:吴涛

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2021-04-20

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 「Workshop」第二十四期 GEO芯片数据处理-1

    图中的Dim1~Dim2分别是指主成分1和主成分2, Dim1代表解释数据变化趋势最多的主成分,Dim2则是解释变化趋势第二多的主成分。括号内的百分比则是代表了...

    王诗翔呀
  • python第二十九课——文件读写(复制文件)

    hankleo
  • python第二十九课——文件读写(读取读取中文字符)

    演示:读取中文字符 结论: 1).如果不设置encoding,默认使用gbk进行编解码 2).如果编码和解码不一致,最终导致报错,但是一旦设置...

    hankleo
  • Python第十课:文件I读写

    这一节我们学习如何读取一个文件,并且打印文件里面的内容。在读取之前我们需要自己建立一个实验文件供我们来做尝试。我们就从txt文件开始,请大家在程序所在的文件夹内...

    HuangWeiAI
  • python第二十九课——文件读写(写数据的操作)

    演示写数据的操作: 结论:往文件中写入数据,如果文件不存在,先创建文件,再写入内容

    hankleo
  • python第二十九课——文件读写(读取数据操作)

    演示读取数据操作: path=r'a.txt' 1.打开文件 f1=open(path,'r') 2.读取数据 content1=f1.read(3) p...

    hankleo
  • python第二十九课——文件读写(readline()和readlines()的使用)

    hankleo
  • 【专知荟萃14】机器翻译 Machine Translation知识资料全集(入门/进阶/综述/视频/代码/专家,附PDF下载)

    【导读】主题荟萃知识是专知的核心功能之一,为用户提供AI领域系统性的知识学习服务。主题荟萃为用户提供全网关于该主题的精华(Awesome)知识资料收录整理,使得...

    WZEARW
  • 图说 | 刚刚结束的AI盛会NIPS 2017上,你需要知道的所有细节

    机器之心
  • 腾讯WeTest&TesterHome 首次联合举办 Workshop-压测篇(上海)

    ? WeTest 导读 腾讯官方的一站式品质开放平台「腾讯WeTest」携手知名测试社区「 TesterHome 」,将腾讯沉淀十余年的品质管理经验凝聚而成,...

    WeTest质量开放平台团队
  • Android开发笔记(三十四)Excel文件的读写

    Android中操作Excel文件的场合较少见,主要是一些专业领域导入导出报表时使用,所以处理Excel读写的开源代码也很稀...

    用户4464237
  • 《环球时报》专访Rails Girls :程序媛,女性力新战场

    “近日,中国第二大英文报纸 Global Times(《环球时报》)对Rails Girls China的组织者文洋和Rails Girls Beijing'5...

    ThoughtWorks
  • 学界 | 跟着大神回顾ACL 2018:大会亮点一览

    很高兴看到很多论文都在从方法上研究现有模型以及它们捕获的内容,而不是一直在引入更新的模型。进行这样的研究最常用的办法是自动创建一个侧重于泛化行为的某个特定方面的...

    机器之心
  • 第十六节:读文件,文件的创建,写文件,文件的读写以及鼠标键盘事件和图形绘制

    用来获取文件本身的信息,如文件所在目录、文件长度、文件读写权限等,不涉及文件的读写操作。

    达达前端
  • 【免费培训】腾讯WeTest&TesterHome WorkShop | 一起学压测

    ? 2019年,中国移动软件市场仍呈现快速增长趋势,移动新生态孕育而生。而移动软件质量问题越发受到用户的关注,成为用户体验的关键因素。目前移动软件测试人才稀缺...

    WeTest质量开放平台团队
  • Serverless+SCF=打倒服务器,解放程序员

    在很多外行人的眼里,程序员就是神一样的存在。他们全年996,节假日无休,不仅Java、PHP、C++要样样精通,还要会修电脑修音响修手机,做前端要懂运维,做后台...

    云加社区技术沙龙
  • 清华姚班90后学霸、MIT博士吴佳俊即将加入斯坦福任助理教授

    近日,“清华学神”、MIT博士生吴佳俊在Twitter上宣布,他将于2020年加入斯坦福大学担任计算机科学助理教授。

    新智元
  • 近九千人齐聚 NeurIPS 2018,四篇最佳论文,十大研究领域,1010 篇论文被接收

    AI 科技评论消息:NeurIPS 2018 于 12 月 3 日—12 月 8 日在加拿大蒙特利尔会展中心(Palais des Congrès de Mon...

    AI科技评论
  • 吴恩达对话LeCun:神经网络跌宕四十年

    最近,这位AI领域的传奇大牛,接受了另一位大牛吴恩达的视频专访。在这次对话中,LeCun回顾了卷积神经网络、反向传播的历史,以及他如何从一个默默无闻的“法国小孩...

    量子位

扫码关注云+社区

领取腾讯云代金券