文章目录
R语言数据处理——基础篇 data.frame基本操作data.frame的创建数据访问、条件筛选与删除数据访问数据筛选删除使用`gather()`进行data.frame数据格式转换常见问题列、行名包括"X"、"V"R语言数据处理——基础篇 data.frame基本操作
打算用两篇博客来记录下平时使用R语言进行数据处理、绘图遇见的一些问题。第一篇首先介绍下使用data.frame处理数据的常用操作,第二篇总结下使用ggplot2绘图时常用的一些操作。每篇博客在基础介绍完后总结下自己遇到过的问题,不定时补充。
data.frame的创建
可以从文件和构造函数创建data.frame。
可以使用以下几个函数从csv、excel文件创建data.frame。
read.csv(file, header = TRUE, sep = ",", quote = "\"", dec = ".", fill = TRUE, comment.char = "", ...)read.csv2(file, header = TRUE, sep = ";", quote = "\"", dec = ",", fill = TRUE, comment.char = "", ...)
主要参数包括
file:文件路径。注意使用相对路径时,是相对工作目录,工作目录绝对路径使用getwd()
查看,以及使用setwd()
设置。
header:是否将文件第一行当作行名,默认为TRUE
。选FALSE
时依然会读取第一行,只不过会自动生成默认行名,使用rowname()<-
更改即可。
sep:csv文件的分隔符,默认为",",常见的分隔符包括","、" “、”;"。
quote:字符的表示方式,默认用" “包围引号。
dec:小数点的表示方式,默认为”.";
fill:当各列变量数不一样时是否填补,默认为TRUE
。注意补充的类型与读取文件后,程序判定的列变量类型有关,如果列变量是数字会用NA
,如果是字符则会用""
,不会用NULL
填补也不能用is.null()
检查。
comment.char:指定读取文件中的注释字符,注释字符及其后不会被读取。
library(readxl)read_excel(path, sheet = NULL, range = NULL, col_names = TRUE, col_types = NULL, na = "", trim_ws = TRUE, skip = 0, n_max = Inf, guess_max = min(1000, n_max), progress = readxl_progress(), .name_repair = "unique") read_xls(path, sheet = NULL, range = NULL, col_names = TRUE, col_types = NULL, na = "", trim_ws = TRUE, skip = 0, n_max = Inf, guess_max = min(1000, n_max), progress = readxl_progress(), .name_repair = "unique") read_xlsx(path, sheet = NULL, range = NULL, col_names = TRUE, col_types = NULL, na = "", trim_ws = TRUE, skip = 0, n_max = Inf, guess_max = min(1000, n_max), progress = readxl_progress(), .name_repair = "unique")
这里给个自己R读取excel所有工作表的写法,
file = 'data.xlsx'sheets <- excel_sheets(file)data <- data.frame()i <- 1for (time in sheets) {data_once <- read_xlsx(file, sheet=time,col_names=F,# range = ,根据数据需要和效率确定读取范围# 参数值见cell-specification: Specify cells for reading)data.once$x <- seq(1, length(rownames(data_once))data = rbind(data, data.once)print(i)i = i + 1}
常用的data.frame构造与辅助函数
可以使用几个相同长度的向量构造data.frame。
time <- 1:3value1 <- c(1, 2, 2)value2 <- c(2, 0, 2)data <- data.frame(time, value1, value2)
创建的data.frame data为
timevalue1value211 1 222 2 033 2 2
当需要创建具有一定规则的向量时,除了使用循环还可以使用以下几个辅助函数:
使用:
创建连续数字的序列,
vector.1 <- 1:5# 1 2 3 4 5
当然也可以使用小数,但是创建的序列步长为1。
vector.2 <- 0.1 2.2# 0.1 1.1 2.1
更改步长可以用seq(from, to, step)
,
vector.3 <- seq(0.1, 2.2, 0.5)# 0.1 0.6 1.1 1.6 2.1
有时候可能需要创建按规则重复的向量,使用rep(vector, repeat_times)
vector.4 <- rep(1:3, 2)# 1 2 3 1 2 3
从辅助函数得到的临时变量创建data.frame时就可以指定列名,不用创建后再更改
data.frame("serial" = 1:4, "value" = rep(c(1, 0), 2))# serial value# 111# 220# 331# 440
数据访问、条件筛选与删除
以前述data为例。
> datatimevalue1value211 1 222 2 033 2 2
数据访问
访问行、列、指定行列数据都可以从索引或行名、列名访问
# 从索引访问第2行data[2,]# time value1 value2# 2 220# 从列名访问列data$value1# 1 2 2# 从行名访问行data["3", ]# time value1 value2# 3 322# 访问指定的其他行列# 只能通过索引操作,不能从行名、列名操作,行名、列名都是字符类型,不支持-操作符,如data[-"2",]、data[,-"value1"]data[-2,]# time value1 value2# 1 112# 3 322
获取行名、列名
rownames(data)# "1" "2" "3"colnames(data)# "time" "value1" "value2"# 通过赋值可以对行名、列名进行更改
数据筛选
常用的筛选包括:
逻辑运算符<
、>
、!=
、==
多个条件,|
或&
。注意别写成||
、&&
包含在指定向量的子向量%in%
以data.2
为例。
data.2 <- data.frame("time" = rep(1:3, 2),"value" = c(data$value1, data$value2),"type" = gl(2, 3, labels = c("value1", "value2")))
> data.2time value type1 11 value12 22 value13 32 value14 12 value25 20 value26 32 value2
筛选value = 0的数据。需要注意筛选操作获得的是基于行或列的一系列布尔值,别忘了","。
data.2[data.2$value == 0, ] # 注意别忘了","# time value type# 5 20 value2
筛选value值在向量[0, 1]中的数据
data.2[data.2$value %in% c(0, 1), ]# time value type# 1 11 value1# 5 20 value2
筛选time < 3且time > 1的数据
data.2[data.2$time > 1 & data.2$time < 3, ]# time value type# 2 22 value1# 5 20 value2
删除
基于上述访问、筛选操作后重新赋值即可实现删除操作。
根据索引删除选定行、列
删除第2行
data.remove_row_2 <- data.2data.remove_row_2 <- data.remove_row_2[-2,]
> data.3time value type1 11 value13 32 value14 12 value25 20 value26 32 value2
按条件筛选
data.remove_type1 <- data.2[data.2$type != "value1",]
> data.remove_rowtime value type4 12 value25 20 value26 32 value2
筛选操作后默认生成的行名可能从1开始或不连续,重新给行名赋值就行
data.rename_row <- data.remove_type1rownames(data.rename_row) <- seq(nrow(data.rename_row))
> data.rename_row time value type1 12 value22 20 value23 32 value2
使用gather()
进行data.frame数据格式转换
前面用到的data、data.2具有不同的形式,前者可能更易读,但是大多数数据处理包和绘图包使用第二种形式。这时可以用tidyr
包中的gather()
进行数据格式的转换。
> datatimevalue1value211 1 222 2 033 2 2
> data.2time value type1 11 value12 22 value13 32 value14 12 value25 20 value26 32 value2
函数参数如下,
gather(data, key = "key", value = "value", ..., na.rm = FALSE, convert = FALSE, factor_key = FALSE)
从data到data.2如下操作即可
library(tidyr)gather(data, value, type, -time)# time type value# 1 1 value11# 2 2 value12# 3 3 value12# 4 1 value22# 5 2 value20# 6 3 value22
简要说下可能的实现方式。
从data到data.2需要对value1、value2两列进行一个转置,再把不进入转置操作的time列对应复制到转置后的数据即可。所以首先选择需要变形的data.frame,接着区分需要转置的列和不需要转置的列,不需要转置的用"-"操作放到其他参数后就行。gather()
函数会将原数据转置区的列名一行视为主键列key,其余行、列的数据依次对应主键变成value列,我们只需要给新的key、value列命名即可。
给个自己的数据当例子。
每个深度有3个传感器,一共有两个深度,测量间隔30 s共测量了120 s。
选择非转置列,重命名新key、value列即可。
library(tidyr)data.example <- read.csv("text.csv")gather(data.example, time, value, -depth, -sensor)# depth sensor timevalue# 11 1 4 0.9784983# 22 1 4 0.9897878# 31 2 4 0.9286928# 42 2 4 0.9376116# 51 3 4 0.9525189# 62 3 4 0.9681960
常见问题
列、行名包括"X"、“V”
读取数据时如果原文件列名、行名为数字,读取后data.frame可能会在数字前加上前缀"X"、“V”。
规则的数据直接利用辅助函数更改列名、行名、指定列。
data.file <- read.csv("data_file.csv")# v1 v2 V3# 1 1 2 3# 2 1 2 3# 3 1 2 3colnames(data.file) <- c(1:length(colnames(data.file))
数据不规则,例如为测试数据值时,进行字符串处理即可,取字符第二位到最后一位。
data.file2 <- read.csv("data_file2.csv")# time X0 X10 X15 X17 X18# 1 value 1 2 3 4 5colnames(data.file2) <- c(colnames(data.file2)[1],sapply(sapply(colnames(data.file2)[-1],substr,2,10), as.numeric))# time 0 10 15 17 18# 1 value 1 2 3 4 5
内部sapply
对指定范围取子字符串,从第2位到第10位(最大位即可,想写函数复用使用max(nchar(colnames(a)))
得到最长字符数),外部sapply
转为数值类型。
P.S.
使用Python pandas时经常弄混两个的函数,考虑写在一起比较还是用一样的模板分开写,欢迎建议。
有问题指出、补充欢迎评论区交流。
如果觉得《R语言数据处理——基础篇 data.frame基本操作》对你有帮助,请点赞、收藏,并留下你的观点哦!