R语言心得说:R语言之xlsx包读写Excel数据

  • 感谢Adrian A. Drǎgulescu发布的xlsx包
    • 工具准备
    • 【基础】简单读取excel文件数据
    • 【基础】简单写入数据到excel文件
    • 【进阶】随心所欲读取excel中的各种信息
    • 【进阶】随心所欲将数据写入excel文件

感谢Adrian A. Drǎgulescu发布的xlsx包

xlsx包提供了必要的工具来与Excel 2007进行交互。用户可以阅读和编写xlsx,并可以通过设置数据格式、字体、颜色和边框来控制电子表格的外观。设置打印区域,缩放控制,创建分割和冻结面板,添加页眉和页脚。包使用Apache POI项目中的java库。本篇主要分享利用xlsx工具包在读写xlsx过程中所碰到的问题及解决办法。

工具准备

强烈建议大家使用RStudio这个IDE,它是以今为止对R语言最友好的一个IDE之一,而且使用很方便。特别是在新包下载安装的时候,只需请求要安装的包名,RStudio会自动将关联的其他包也一并下载并安装。

  1. 安装R、安装RStudio;
  2. 一个简单的示例数据(本次以iris鸢尾花数据为例);
  3. 下载安装xlsx(Rstudio会同步下载并安装rJava, xlsxjars两个包);
> # 下载并安装xlsx包
> install.packages("xlsx")
> library(xlsx)

【基础】简单读取excel文件数据

假如是csv或txt等文本类的数据文件,利用R内置函数read.csv()与read.table()就可读取(注意编码格式的参数设置)。Excel由于使用范围最广,很多问题不可避免,因此,xlsx包提供了专门读取xlsx的函数read.xlsx和read.xlsx2,为什么有两个呢?请看以下区别:

函数 参数
xlsx::read.xlsx() file, sheetIndex, sheetName=NULL, rowIndex=NULL,startRow=NULL,endRow=NULL, colIndex=NULL,as.data.frame=TRUE, header=TRUE, colClasses=NA,keepFormulas=FALSE, encoding=“unknown”, password=NULL, …
xlsx::read.xlsx2() file, sheetIndex, sheetName=NULL, startRow=1,colIndex=NULL, endRow=NULL, as.data.frame=TRUE, header=TRUE,colClasses=“character”, password=NULL, …

其实只是细微的差别,大家自己体会即可。下面给个参考案例:

> # 指定file和sheetIndex(或sheetName),即可定位到相应的工作表
> data1 <- read.xlsx("iris.xlsx",sheetIndex = 1)
> head(data1)
Sepal.Length Sepal.Width Petal.Length Petal.Width Species
5.1 3.5 1.4 0.2 setosa
4.9 3.0 1.4 0.2 setosa
4.7 3.2 1.3 0.2 setosa
4.6 3.1 1.5 0.2 setosa
5.0 3.6 1.4 0.2 setosa
5.4 3.9 1.7 0.4 setosa

【基础】简单写入数据到excel文件

切莫用R内置函数read.csv()与read.table()去生成xlsx文件,会有你意想不到的麻烦,还是采用专业的包来解决问题吧。
xlsx包同样提供了两个写入数据的函数write.xlsx()和write.xlsx2(),其中细微区别自行参透(注意参数 ...)。

函数 参数
xlsx::write.xlsx() x, file, sheetName=“Sheet1”, col.names=TRUE, row.names=TRUE, append=FALSE, showNA=TRUE, password=NULL
xlsx::write.xlsx2() x, file, sheetName=“Sheet1”,col.names=TRUE, row.names=TRUE, append=FALSE, password=NULL, ...

下面是参考案例:

># 指定x待写入数据,file生成的文件名,row.names为false则不生成行名,指定sheet工作表名为Sheet1
>write.xlsx(iris, file = "iris.xlsx", row.names = FALSE, sheetName = "Sheet1")

想必会有人在这里踩坑,大家应该注意到有一个append的参数,是否认为将其值设置为TRUE的话,就可以多次向表中写入数据?那就真踩坑了。查看xlsx包中的注释也很模糊:

> # a logical value indicating if x should be appended to an existing file.
> # 翻译:一个逻辑值,指示是否应该将x附加到现有文件中。

附加到现有文件中,实际上是增加新的sheet,而非在原有sheet工作表中继续增加数据。如需在同一个sheet工作表中多次增加数据,请继续往下看。

【进阶】随心所欲读取excel中的各种信息

随心所欲 一点不夸张,不仅可以取出excel中的数据,还能识别excel单元格的样式(包括颜色、字体、大小、标注、数据类型等等)。其原理与数据库有点相似,先是定义一个工作簿的对象,再基于工作簿定义里面的工作表,进而逐级查询。下面进行详细介绍:
【样例数据】文件名:iris10.xlsx。

  • 声明一个工作簿对象
> # loadWorkbook(file, password=NULL)    #用于声明一个工作簿对象
> # 提醒:如果excel文件不在工作空间内,file最好指定为绝对路径
> wb <- createWorkbook("iris10.xlsx")
  • 检索工作簿中的sheet
> # sheets <- getSheets(wb)    #用于生成一个list对象,其中包含所有工作表的信息,数据类型为rJava::jobjRef,在此不深入讲解
> sheets <- getSheets(wb)
  • 定位目标sheet
> # 本例只有一个sheet,名称为“Sheet1”
> sheet <- sheets[["Sheet1"]]    # sheet的数据类型为rJava::jobjRef
  • 读取数据【方法一】
    上面read.xlsx()方法能够将整个sheet工作表的数据读取出来,在这里提供另一种方法,不过相对麻烦一点,使用的是xlsx::readColumns()函数
函数 参数
xlsx::readColumns() sheet,startColumn,endColumn,startRow,endRow=NULL,as.data.frame=TRUE,header=TRUE, colClasses=NA, …
xlsx::readRows() sheet, startRow, endRow, startColumn, endColumn=NULL

xlsx::readRows()使用起来比较麻烦,不如xlsx::readColumns()好用,有兴趣的可自行研究一下。
另外还有两个函数,用于定位表内数据第一行和最后一行的索引(这里与Java的性质一致,从0开始算起)

函数 参数
getFirstRowNum() 无参。该函数必须基于sheet对象
getLastRowNum() 无参。该函数必须基于sheet对象

下面以xlsx::readColumns()为例获取数据:

> # 该函数必须提供数据的起始列索引值、终止列索引值、起始行索引值、终止行索引值;
> dataTmp <- readColumns(sheet, startColumn = 1, endColumn = 10,startRow = sheet$getFirstRowNum()+1, endRow = sheet$getLastRowNum()+1,header = T, as.data.frame=TRUE)

as.data.frame=TRUE决定了输出结果为一个数据框。
缺点:在不清楚数据结构的情况下,首行和末行索引值可以求得,但列数一般难以确定,可能导致列缺失或生成多余的列

  • 读取数据【方法二】
    另一种方法相对【方法一】要好一点,先是将所有单元格的值获取出来,再生成数据框。(稍微复杂一点)
函数 参数 注释
xlsx::getRows() sheet, rowIndex=NULL 用于获取sheet的每一行数据,返回值list,数据类型为rJava::jobjRef
xlsx::getCells() row, colIndex=NULL, simplify=TRUE 用于获取行内每个单元格的数据,返回值list,数据类型为rJava::jobjRef
xlsx::getCellValue() cell, keepFormulas=FALSE, encoding=“unknown” 用于获取所有单元格的值,返回值list,数据类型为character,长度为数据表m*n

注意:这里连同标题行也作为单元格数据一并获取,并且如果有null值的单元格,会跳过该单元格

> # 获取cells进而获取values
> cells <- sheet %>% getRows() %>% getCells()
> values <- lapply(cells,getCellValue)

values获取出来就如下面这个样子,你会发现value的名称向量,每个值都包含了所在单元格的x、y坐标值。

> names(values)    #查看values的名称向量[1] "1.1"  "1.2"  "1.3"  "1.4"  "1.5"  "2.1"  "2.2"  "2.3"  "2.4"  "2.5"  "3.1"  "3.2"  "3.3"  "3.4"  "3.5"  "4.1"
[17] "4.2"  "4.3"  "4.4"  "4.5"  "5.1"  "5.2"  "5.3"  "5.4"  "5.5"  "6.1"  "6.2"  "6.3"  "6.4"  "6.5"  "7.1"  "7.2"
[33] "7.3"  "7.4"  "7.5"  "8.1"  "8.2"  "8.3"  "8.4"  "8.5"  "9.1"  "9.2"  "9.3"  "9.4"  "9.5"  "10.1" "10.2" "10.3"
[49] "10.4" "10.5" "11.1" "11.2" "11.3" "11.4" "11.5"

将这些坐标值拆分出来,作为等会重排数据的索引

> addresses <- sapply(names(values),FUN = function(x) str_split(string = x,pattern = "[.]"))

接下来就只需要将其进行重排,形成数据框即可。

> datas.name <- vector(mode = "character")    #声明一个空的向量,用来存放标题
> datas <- data.frame()    # 声明一个空的数据框,用来存放目标数据
> # 用sapply代替for做循环,避免占用大量内存。同时注意sapply使用时的环境问题,用.GlobalEnv指向最外层环境的变量。
> # 这里只对数据进行重排,无需进行计算,所以invisible不显示计算结果
> invisible(sapply(addresses,FUN = function(x) {
+   if (x[1] == "1") {
+     .GlobalEnv$datas.name = c(.GlobalEnv$datas.name,.GlobalEnv$values[[1]])
+     .GlobalEnv$values[[1]] <- NULL
+   } else {
+     .GlobalEnv$datas[x[1],x[2]] <- .GlobalEnv$values[[1]]
+     .GlobalEnv$values[[1]] <- NULL
+   }
+ }))
> names(datas) <- datas.name    #最后在添加标题
> View(datas)

得到结果与原excel数据一致

获取单元格样式与获取数据的方式一致,这里不再增加过多篇幅讲解,只做简单介绍。以下函数按函数名字面理解。

函数 参数
xlsx::CellStyle() wb, dataFormat=NULL, alignment=NULL,border=NULL, fill=NULL, font=NULL, cellProtection=NULL
xlsx::setCellStyle() cell, cellStyle
xlsx::getCellStyle() cell
xlsx::createCellComment() cell, string="", author=NULL, visible=TRUE
getCellComment() cell
removeCellComment() cell

其他函数后续如有机会,再做详细介绍吧。

【进阶】随心所欲将数据写入excel文件

我想大家更想看到的就是这部分内容了。确实在日常处理数据时,将数据存储到excel中进行传递是常有的事,谁叫excel是微软亲生的呢。闲话少说,直入正题。
前面基础篇通过write.xlsx()函数将数据写入excel文件中,同时指定sheet名称。但这种写入是一次性的,即一次写入多少就多少。在工作簿里面新增sheet工作表用append控制,但在同个sheet上继续写入数据,会报错:

> write.xlsx(datas,file = "iris10.xlsx",sheetName = "Sheet1",row.names = F,append = T)
Error in .jcall(wb, "Lorg/apache/poi/ss/usermodel/Sheet;", "createSheet",  : java.lang.IllegalArgumentException: The workbook already contains a sheet of this name

说是这个名称的sheet已经存在同名的了!

这次我们采用高级一点的方法,跟前面进阶读取数据一样,先是定义一个工作簿的对象,再创建或加载sheet工作表。

函数 参数 注释
xlsx::createWorkbook() type=“xlsx” 用于生成一个新的excel工作簿
xlsx::loadWorkbook() file, password=NULL 用于加载当前已存在的excel工作簿
xlsx::saveWorkbook() wb, file, password=NULL 使用完必须保存工作簿
xlsx::createSheet() wb, sheetName=“Sheet1” 用于生成一个新的sheet工作表
xlsx::removeSheet() wb, sheetName=“Sheet1” 用于删除工作表
xlsx::getSheets() wb 用于获取当前工作簿里的工作表清单,返回值是list
xlsx::addDataFrame() x, sheet, col.names=TRUE, row.names=TRUE,startRow=1, 用于获取当前工作簿里的工作表清单,返回值是list
(续上) startColumn=1,colStyle=NULL, colnamesStyle=NULL,rownamesStyle=NULL, showNA=FALSE, characterNA="", byrow=FALSE

前面讲过如何加载已有工作簿,这里以生成新excel工作簿为例,将数据写入文件中

> wb <- xlsx::createWorkbook()
> sheets <- getSheet()
# 新生成的工作簿没有sheet,系统提示:Workbook has no sheets!
> sheet <- createSheet(wb,sheetName = "newSheet1")

此时R内存中已经生成了一个工作簿,包含一个空的sheet工作表,通过addDataFrame()函数将数据写入sheet中.

> # 用上面生成的datas数据框对象,取前4行数据写入当前sheet对象中
> addDataFrame(data[1:4,],sheet,row.names = F)
> saveWorkbook(wb,file = "iris_new.xlsx")
                               ==记得保存工作簿、记得保存工作簿、记得保存工作簿==

如果是在已有excel工作簿上操作,这里最好做一个判断,避免覆盖现有数据,造成不必要的麻烦。如果当前sheet的最后一行索引不等于零(说明有数据),则将新数据写到最后一行数据的下一行,同时不加入列名行(col.names = FALSE);如果为零则将数据直接添加到sheet中。

> # 用上面生成的datas数据框对象,取前4行数据写入当前sheet对象中
> if (sheet$getLastRowNum() != 0) {
+          addDataFrame(data[1:4,],sheet,row.names = F,col.names = F,startRow = sheet$getLastRowNum() + 2)
+        } else {
+          addDataFrame(data[1:4,],sheet,row.names = F)
+        }
+ }
> saveWorkbook(wb,file = "iris_new.xlsx")

至此,你应该知道如何在原有工作表基础上新增数据行了吧?多么方便!!
如果要增加新的sheet工作表,只需将sheet重新定义一个新的sheetName即可。

好了,在大家面前献丑了,感谢阅读!有疑问或想与我交流,可留言。

附上一条小资料,纯当友情推广,共同进步:Read Excel files from R

R语言心得说:R语言之xlsx包读写Excel数据相关推荐

  1. c语言心得100,c语言课程设计心得体会

    c语言课程设计心得体会 c语言课程设计心得体会范文一: 课程设计是培养学生综合运用所学知识,发现,提出,分析和解决实际问题,锻炼实践能力的重要环节,是对学生实际工作能力的具体训练和考察过程.随着科学技 ...

  2. python读取xlsx python读取excel数据

    如题 python pandas读取excel数据 如何读取特定sheet的excel数据 1.安装pandas 已经有的可以不用再安装 >pip install pandas 2.读取数据 首 ...

  3. Julia通过XLSX.jl包读写Excel文件

    版本:0.8.4 官方链接:Tutorial · XLSX.jl API速查表 函数 作用 XLSX.XLSXFile XLSXFile 表示对 Excel 文件的引用 XLSX.readxlsx 将 ...

  4. R语言中判断是否是整数。以及读写excel

    今天接手一个重复性工作, 需要手工把产品运营们在excel里写的活动规则, 插入数据库表中.为了减少出错, 提高效率. 再加上最近刚刚学R语言, 就用R练练手, 自动生成mysql的sql语句. 一次 ...

  5. c语言心得100,c语言实训心得精选范文

    在科技高度发展的今天,计算机在人们之中的作用越来越突出.而c语言作为一种计算机的语言,我们学习它,有助于我们更好的了解计算机,与计算机进行交流,因此,c语言的学习对我们尤其重要. 在这个星期里,我们专 ...

  6. R语言安装xlsx包以及可能遇到的问题

    文章目录 步骤1:java下载和安装 步骤2:安装和导入xlsx 加载的时候可能出现的问题 参考文献 步骤1:java下载和安装 下载和安装过程见 Java 的下载安装教程,过程很详细,其中cmd部分 ...

  7. R语言Logistic回归模型案例基于AER包的affair数据分析

    R语言Logistic回归模型案例基于AER包的affair数据 目录 R语言Logistic回归模型案例基于AER包的affair数据 #数据加载及目标变量二值化

  8. R语言--readr包读写数据

    文章目录 前言 一.发现问题 二.分析问题 三.解决问题 四.读写速度 总结 吐槽 前言 当你使出了浑身解数,read.csv和read.table还是无法读入数据时,或许可以尝试一下readr包中的 ...

  9. R读写Excel文件中数据的方法

    用R语言读写Excel的方法有很多,但每种方法都有让人头疼的地方,比如xlsx包的代码复杂,只支持Excel2007:RODBC不易理解,限制太多,程序不稳定,会出各种怪毛病.另存为csv格式的方法倒 ...

最新文章

  1. php t double arrow,关于php:php – 语法错误,意外T_DOUBLE_ARROW
  2. 帮我看看这个是什么意思 c++代码
  3. oracle中怎样查询用户权限
  4. D2 AJAX 封装策略
  5. 按指定格式拼接字符串
  6. android检查可用网络的代码
  7. 【kafka】Kafka Fetch Session 剖析
  8. Visio图片转为eps格式
  9. 泛微E8的数据展示集成方法
  10. 2017年信息学奥赛NOIP普及组试题
  11. 麻省理工学院计算机硕士几年制,2020年麻省理工学院硕士读几年
  12. PowerDesigner 15 License Key失效的解决方案
  13. 如何创建一个最简单的Windows桌面应用程序 (C++)
  14. DHTML Cascading style sheet 下载 CSS手册
  15. spark 相关性分析_《Spark机器学习进阶实战》——2.3.2 相关性分析
  16. html怎么搞一个微信图标,怎样在微信名字添加图标和微信名字里怎么加表情?什么系统都可以...
  17. R语言ggcharts包的dumbbell_chart函数可视化哑铃图(对比两个年份数据的差异)、scale_y_continuous函数中的labels参数自定义设置X轴坐标标签的格式
  18. springboot实战,实现发送邮件,gmail邮件,包括发送附件还有正文,以及注意覆盖问题
  19. 网站制作笔记-bootstrap可视化布局,表单生成工具,快速制作网页原型
  20. [C++][muduo]1-muduo安装和运行

热门文章

  1. 飞扬的小鸟java分析_刷题总结——飞扬的小鸟(NOIP2014提高组)
  2. 大商创MySQL不支持_大商创配置文件config.php详解
  3. Kali安装的一些常用软件
  4. 计算机考试答题设计用例图,学生网上考试系统的设计与实现
  5. backtrack回溯算法
  6. COCOS学习笔记--TexturePacker使用详解
  7. 国内食品品牌策划公司排名,食品品牌设计公司哪家好?2021最新
  8. 在Mac OS X苹果lion系统上制作USB启动盘
  9. Python 中 send的解释
  10. Threejs系列--11游戏开发--沙漠赛车游戏【初步加载地面】