R语言中的数据框data.frame被定义为由不同变量值(列)和不同观察值(行)所组成的二维数据结构,每一列存储的数据类型必须相同,不同数据列的数据类型可以相同,也可以不同,但是每列的行数(长度)必须相同。其实R数据框就是标准的Excel表格数据,对,你可以这样理解……
数据框是R语言进行数据处理和分析常用的数据结构类型,这也为什么R的内置数据集有占46%的是数据框。通常用R基础函数read.table()读取的excel表格数据,在R中存储为数据框data.frame或者列表list。
数据框的特征很有意思,关于数据框实用方法有很多,都是为解决现实实际问题而发展出来的方法,关于R数据框的知识和使用方法书上的案例比较呆板老旧,网上的一般资源又比较零散和随意,往往你查到的不是你想要的。
我现在集中精力帮助大家整理出一个实用的、有效的、可以当速查救命手册的帮助文档来!接下来一系列简书日更将主要对数据框进行总结和分享,希望能帮到大家!对我也是一次比较重要的R知识的整理、归纳、总结和提升。
当你参透R数据框的时候,其实你的R语言已经达到一定的水平了……
#### 1.1 data.frame()创建
df <- data.frame(编号 = 1:10, 姓名 = c("王明", "李磊", "张乐", "刘能", "黄粲", "赵月", "朱忻", "陈振", "武琳", "孙晔"), 性别 = c("男", "男", "男", "男", "女", "女", "女", "男", "女", "女"), 数学成绩 = c("90", "88", "80", "70", "95", "91", "90", "81", "80", "76"), 语文成绩 = c("91", "75", "83", "89", "90", "91", "88", "77", "85", "90"))
#@ 查看df内容
df
# 编号 姓名 性别 数学成绩 语文成绩
# 1 1 王明 男 90 91
# 2 2 李磊 男 88 75
# 3 3 张乐 男 80 83
# 4 4 刘能 男 70 89
# 5 5 黄粲 女 95 90
# 6 6 赵月 女 91 91
# 7 7 朱忻 女 90 88
# 8 8 陈振 男 81 77
# 9 9 武琳 女 80 85
# 10 10 孙晔 女 76 90
class(df)
# [1] "data.frame"
#### 1.2 as.data.frame()强制转换其他数据结构为数据框
data(volcano) # 载入内置数据集volcano
class(volcano)
# [1] "matrix"
df1 <- as.data.frame(volcano)
class(df1)
# [1] "data.frame"
library(datasets)
data(state)
class(state.center) # 查看state.center的数据结构类型
# [1] "list"
df2 <- as.data.frame(state.center)
head(df2)
# x y
# 1 -86.7509 32.5901
# 2 -127.2500 49.2500
# 3 -111.6250 34.2192
# 4 -92.2992 34.7336
# 5 -119.7730 36.5341
# 6 -105.5130 38.6777
class(df2)
# [1] "data.frame"
data(iris3) # 载入内置数据集
class(iris3)
# [1] "array"
head(iris3)
# [1] 5.1 4.9 4.7 4.6 5.0 5.4
df3 <- as.data.frame(iris3)
class(df3)
# [1] "data.frame"
head(df3)
# Sepal L..Setosa Sepal W..Setosa Petal L..Setosa
# 1 5.1 3.5 1.4
# 2 4.9 3.0 1.4
# 3 4.7 3.2 1.3
# 4 4.6 3.1 1.5
# 5 5.0 3.6 1.4
# 6 5.4 3.9 1.7
# Petal W..Setosa Sepal L..Versicolor Sepal W..Versicolor
# 1 0.2 7.0 3.2
# 2 0.2 6.4 3.2
# 3 0.2 6.9 3.1
# 4 0.2 5.5 2.3
# 5 0.2 6.5 2.8
# 6 0.4 5.7 2.8
# Petal L..Versicolor Petal W..Versicolor Sepal L..Virginica
# 1 4.7 1.4 6.3
# 2 4.5 1.5 5.8
# 3 4.9 1.5 7.1
# 4 4.0 1.3 6.3
# 5 4.6 1.5 6.5
# 6 4.5 1.3 7.6
# Sepal W..Virginica Petal L..Virginica Petal W..Virginica
# 1 3.3 6.0 2.5
# 2 2.7 5.1 1.9
# 3 3.0 5.9 2.1
# 4 2.9 5.6 1.8
# 5 3.0 5.8 2.2
# 6 3.0 6.6 2.1
#@ 以上转换在条件满足的时候是可以相互强制转换的,例如:可以矩阵到数据框,也可以数据框到矩阵。
#### 1.3 R函数读取数据文件,存为数据框对象
#@ 为了大家测试方便,我们先用R内置函数write.csv保存R一个内置数据框数据集到本地:mtcars,然后再读取这个表格文件:mtcars.csv,用下面三种方法读取。这个文件默认保存到你的工作目录中,查看你的工作目录的方法是getwd(),也可以直接用函数dir()查看,如果你设置了自己的工作路径,那这个文件就在你的当前工作路径内
data("mtcars")
dim(mtcars)
# [1] 32 11
class(mtcars)
# [1] "data.frame"
write.csv(mtcars, file = "mtcars.csv")
dir()
# [1] "mtcars.csv"
# [2] "R数据框实用操作方法大总结.docx"
# [3] "简书日更挑战_20191222_Sunday.R"
#@ 我的已经保存到本地电脑文件夹中了(当前工作目录)
getwd()
# [1] "E:/学习空间/博客/简书/简书日更挑战/2019年/12月/20191222_Sunday"
#@ 现在我们用函数读取数据文件
#@ read.table(),R基础函数
df4 <- read.table("mtcars.csv", sep = ",", header = T)
dim(df4)
# [1] 32 11
class(df4)
# [1] "data.frame"
#@ read.xlsx(),R扩增包openxlsx函数,使用这个函数之前你需要安装这个包:openxlsx,如果已经安装就OK,没有的话执行安装代码:install.packages("openxlsx"),安装成功之后就可以往下走了,然后手动操作一下,用Excel软件打开我们刚才保存的mtcars.csv文件,然后另存为xlsx文件,文件格式变为.xlsx,文件名不变,还是mtcars,然后关闭文件,执行dir()
dir()
# [1] "mtcars.csv"
# [2] "mtcars.xlsx"
# [3] "R数据框实用操作方法大总结.docx"
# [4] "简书日更挑战_20191222_Sunday.R"
#@ 我们看到多出一个mtcars.xlsx文件
df5 <- openxlsx::read.xlsx("mtcars.xlsx", sheet = 1, startRow = 1, colNames = T, rowNames = T, detectDates = FALSE)
dim(df5)
# [1] 32 11
class(df5)
# [1] "data.frame"
#@ import(),R扩增包rio函数import(),同样这个是扩增包,使用前需要安装rio包,安装完成之后就可以继续往下走了
df6 <- rio::import("mtcars.csv", sep = ",")
df7 <- rio::import("mtcars.xlsx")
#@ 神包rio就这个牛,这只是小试牛刀,它可以支持32种格式文件的读和写
#@ 使用SQL查询Data Frame对象或者数据库文件,sqldf包,同样使用前需要安装它
library(sqldf)
# 载入需要的程辑包:gsubfn
# 载入需要的程辑包:proto
# 载入需要的程辑包:RSQLite
library(chron) # 同样使用前需要安装
DF <- read.table(textConnection(Lines), skip = 1, as.is = TRUE, col.names = c("Id", "Date", "Time", "Quality", "Lat", "Long"))
DF
# Id Date Time Quality Lat Long
# 1 STM05-1 28/02/2005 17:35 Good -35.562 177.158
# 2 STM05-1 28/02/2005 19:44 Good -35.487 177.129
# 3 STM05-1 28/02/2005 23:01 Unknown -35.399 177.064
# 4 STM05-1 01/03/2005 07:28 Unknown -34.978 177.268
# 5 STM05-1 01/03/2005 18:06 Poor -34.799 177.027
# 6 STM05-1 01/03/2005 18:47 Poor -34.850 177.059
# 7 STM05-2 28/02/2005 12:49 Good -35.928 177.328
# 8 STM05-2 28/02/2005 21:23 Poor -35.926 177.314
dim(DF)
# [1] 8 6
class(DF)
# [1] "data.frame"
str(DF)
# 'data.frame': 8 obs. of 6 variables:
# $ Id : chr "STM05-1" "STM05-1" "STM05-1" "STM05-1" ...
# $ Date : chr "28/02/2005" "28/02/2005" "28/02/2005" "01/03/2005" ...
# $ Time : chr "17:35" "19:44" "23:01" "07:28" ...
# $ Quality: chr "Good" "Good" "Unknown" "Unknown" ...
# $ Lat : num -35.6 -35.5 -35.4 -35 -34.8 ...
# $ Long : num 177 177 177 177 177 ...
#@ 用transform()对数据框对象进行操作,为原数据框添加新的列,改变原变量列的值,通过赋值NULL删除列变量
DF2 <- transform(DF, Date = chron(Date, format = "d/m/y"), Time = times(paste(Time, "00", sep = ":")), Quality = factor(Quality, levels = c("Good", "Poor", "Unknown")))
dim(DF2)
# [1] 8 6
class(DF2)
# [1] "data.frame"
#@ 用sqldf函数获取R内置数据集
data("mtcars")
DF3 <-sqldf("select am,hp,mpg from mtcars where cyl='4' and wt<3")
DF3
# am hp mpg
# 1 1 93 22.8
# 2 1 66 32.4
# 3 1 52 30.4
# 4 1 65 33.9
# 5 0 97 21.5
# 6 1 66 27.3
# 7 1 91 26.0
# 8 1 113 30.4
# 9 1 109 21.4
class(DF3)
# [1] "data.frame"
#@ R就是这么强大!
dim(df) # 我们利用函数data.frame手动创建了一个10行、5列的数据框,即10个观察值:"1" "2" "3" "4" "5" "6" "7" "8" "9" "10",5个变量值:"编号" "姓名" "性别" "数学成绩" "语文成绩"
# [1] 10 5
attributes(df)
# $names
# [1] "编号" "姓名" "性别" "数学成绩" "语文成绩"
#
# $class
# [1] "data.frame"
#
# $row.names
# [1] 1 2 3 4 5 6 7 8 9 10
str(df)
# 'data.frame': 10 obs. of 5 variables:
# $ 编号 : int 1 2 3 4 5 6 7 8 9 10
# $ 姓名 : Factor w/ 10 levels "陈振","黄粲",..: 6 3 8 4 2 9 10 1 7 5
# $ 性别 : Factor w/ 2 levels "男","女": 1 1 1 1 2 2 2 1 2 2
# $ 数学成绩: Factor w/ 8 levels "70","76","80",..: 6 5 3 1 8 7 6 4 3 2
# $ 语文成绩: Factor w/ 8 levels "75","77","83",..: 8 1 3 6 7 8 5 2 4 7
#### 3.1 数据框行查看及操作
df
# 编号 姓名 性别 数学成绩 语文成绩
# 1 1 王明 男 90 91
# 2 2 李磊 男 88 75
# 3 3 张乐 男 80 83
# 4 4 刘能 男 70 89
# 5 5 黄粲 女 95 90
# 6 6 赵月 女 91 91
# 7 7 朱忻 女 90 88
# 8 8 陈振 男 81 77
# 9 9 武琳 女 80 85
# 10 10 孙晔 女 76 90
rownames(df) # 查看df的行名
# [1] "1" "2" "3" "4" "5" "6" "7" "8" "9" "10"
row.names(df)
# [1] "1" "2" "3" "4" "5" "6" "7" "8" "9" "10"
NROW(df) # 统计有多少行
# [1] 10
row.names.data.frame(df) # 查看数据框的行名
# [1] "1" "2" "3" "4" "5" "6" "7" "8" "9" "10"
#@ 对行数据进行求平均值rowMeans()
dim(df1)
# [1] 87 61
df1[1:5,1:5]
# V1 V2 V3 V4 V5
# 1 100 100 101 101 101
# 2 101 101 102 102 102
# 3 102 102 103 103 103
# 4 103 103 104 104 104
# 5 104 104 105 105 105
df1_rowmean <- rowMeans(df1)
length(df1_rowmean)
# [1] 87
class(df1_rowmean)
# [1] "numeric"
#@ 对行数据进行求和rowSums()
df1_rowsum <- rowSums(df1)
length(df1_rowsum)
# [1] 87
class(df1_rowsum)
# [1] "numeric"
#### 3.2 数据框列查看及操作
colnames(df)
# [1] "编号" "姓名" "性别" "数学成绩" "语文成绩"
#@ 对数据框列进行求平均colMeans()
df1_colmean <- colMeans(df1)
length(df1_colmean)
# [1] 61
class(df1_colmean)
# [1] "numeric"
#@ 对数据框列进行求和colSums()
df1_colsum <- colSums(df1)
length(df1_colsum)
# [1] 61
class(df1_colsum)
# [1] "numeric"
#### 3.3 其他的操作
#@ 当前你也可以对数据框整体或者行、列求其他的值:例如最小值、最大值、对数值、幂值、方差、标准差、MAD等等,前题是这个数据框是数值型的数据框,因为字符串无法参与计算
max(df)
# Error in FUN(X[[i]], ...) : 只适用于全数值数据框
max(df1)
# [1] 195
min(df1)
# [1] 94
df1_log2 <- log2(df1)
dim(df1_log2)
# [1] 87 61
df1[1:5,1:5]
# V1 V2 V3 V4 V5
# 1 100 100 101 101 101
# 2 101 101 102 102 102
# 3 102 102 103 103 103
# 4 103 103 104 104 104
# 5 104 104 105 105 105
df1_log2[1:5,1:5]
# V1 V2 V3 V4 V5
# 1 6.643856 6.643856 6.658211 6.658211 6.658211
# 2 6.658211 6.658211 6.672425 6.672425 6.672425
# 3 6.672425 6.672425 6.686501 6.686501 6.686501
# 4 6.686501 6.686501 6.700440 6.700440 6.700440
# 5 6.700440 6.700440 6.714246 6.714246 6.714246
df1_row1_log2 <- log2(df1[1,]) # 只对第一行进行log2转化
df1_row1_log2[1:5,1:5]
# V1 V2 V3 V4 V5
# 1 6.643856 6.643856 6.658211 6.658211 6.658211
# NA NA NA NA NA NA
# NA.1 NA NA NA NA NA
# NA.2 NA NA NA NA NA
# NA.3 NA NA NA NA NA
df1_col1_log2 <- log2(df1[,1]) # 只对第一列进行log2转化
head(df1_col1_log2)
# [1] 6.643856 6.658211 6.672425 6.686501 6.700440 6.714246
sum(df1) # 对数值型的数据框求和
# [1] 690907
#@ 其他的自己去测试,记住R可以计算一切数学计算,如果没有现成的工具就自己构建工具
df
# 编号 姓名 性别 数学成绩 语文成绩
# 1 1 王明 男 90 91
# 2 2 李磊 男 88 75
# 3 3 张乐 男 80 83
# 4 4 刘能 男 70 89
# 5 5 黄粲 女 95 90
# 6 6 赵月 女 91 91
# 7 7 朱忻 女 90 88
# 8 8 陈振 男 81 77
# 9 9 武琳 女 80 85
# 10 10 孙晔 女 76 90
#### 4.1 根据某一元素,提取行,然后存为一个新的数据框
#@ 提取数据框df中所有男生的信息
df_new1 <- df[which(df$性别 == "男"),]
df_new1
编号 姓名 性别 数学成绩 语文成绩
1 1 王明 男 90 91
2 2 李磊 男 88 75
3 3 张乐 男 80 83
4 4 刘能 男 70 89
8 8 陈振 男 81 77
#@ 提取数据框df中所有女生的信息
df_new2 <- df[which(df$性别 == "女"),]
df_new2
# 编号 姓名 性别 数学成绩 语文成绩
# 5 5 黄粲 女 95 90
# 6 6 赵月 女 91 91
# 7 7 朱忻 女 90 88
# 9 9 武琳 女 80 85
# 10 10 孙晔 女 76 90
#### 4.2 根据某一个元素,提取列,然后另存为一个新的数据框
df_new3 <- df[,4:5]
df_new3
# 数学成绩 语文成绩
# 1 90 91
# 2 88 75
# 3 80 83
# 4 70 89
# 5 95 90
# 6 91 91
# 7 90 88
# 8 81 77
# 9 80 85
# 10 76 90
df_new4 <- df[2:4, 2:4] # 提取数据框的一小部分:子集
df_new4
# 姓名 性别 数学成绩
# 2 李磊 男 88
# 3 张乐 男 80
# 4 刘能 男 70
df[2,2]
# [1] 李磊
# 10 Levels: 陈振 黄粲 李磊 刘能 孙晔 王明 武琳 张乐 ... 朱忻
df[3,3]
# [1] 男
# Levels: 男 女
df[4,4]
# [1] 70
#@ 根据条件筛选数据框
df_new5 <- df[df$数学成绩 > 80,]
df_new5
# 编号 姓名 性别 数学成绩 语文成绩
# 1 1 王明 男 90 91
# 2 2 李磊 男 88 75
# 5 5 黄粲 女 95 90
# 6 6 赵月 女 91 91
# 7 7 朱忻 女 90 88
# 8 8 陈振 男 81 77
df_new6 <- df[df$语文成绩 == 91,]
df_new6
# 编号 姓名 性别 数学成绩 语文成绩
# 1 1 王明 男 90 91
# 6 6 赵月 女 91 91
#@ 多条件判断进行数据框的筛选
df_new7 <- df[c(df$性别 == "男" & df$数学成绩 == 90),]
df_new7
# 编号 姓名 性别 数学成绩 语文成绩
# 1 1 王明 男 90 91
df_new8 <- df[df$性别 == "女" & df$数学成绩 > 90 & df$语文成绩 >90,]
df_new8
# 编号 姓名 性别 数学成绩 语文成绩
# 6 6 赵月 女 91 91
#### 5.1 按照某一列进行排序
#@ 默认是升序排序,由低到高排序
df_new9 <- df[order(df$数学成绩),]
df_new9
# 编号 姓名 性别 数学成绩 语文成绩
# 4 4 刘能 男 70 89
# 10 10 孙晔 女 76 90
# 3 3 张乐 男 80 83
# 9 9 武琳 女 80 85
# 8 8 陈振 男 81 77
# 2 2 李磊 男 88 75
# 1 1 王明 男 90 91
# 7 7 朱忻 女 90 88
# 6 6 赵月 女 91 91
# 5 5 黄粲 女 95 90
#@ 也可以降序排序:由高到低进行
df_new10 <- df[order(-df$数学成绩),]
df_new10
# 编号 姓名 性别 数学成绩 语文成绩
# 5 5 黄粲 女 95 90
# 6 6 赵月 女 91 91
# 1 1 王明 男 90 91
# 7 7 朱忻 女 90 88
# 2 2 李磊 男 88 75
# 8 8 陈振 男 81 77
# 3 3 张乐 男 80 83
# 9 9 武琳 女 80 85
# 10 10 孙晔 女 76 90
# 4 4 刘能 男 70 89
#### 5.2 按照多个列进行排序
#@ 多列同为升序排序,有主次之分,第一个是主要的,先排第一个OK了之后,再排第二个,考虑到一列有相同的排序,第二列、第三列大小不一……,才可以区分开
df_new11 <- df[order(df$数学成绩, df$语文成绩),]
df_new11
# 编号 姓名 性别 数学成绩 语文成绩
# 4 4 刘能 男 70 89
# 10 10 孙晔 女 76 90
# 3 3 张乐 男 80 83
# 9 9 武琳 女 80 85
# 8 8 陈振 男 81 77
# 2 2 李磊 男 88 75
# 7 7 朱忻 女 90 88
# 1 1 王明 男 90 91
# 6 6 赵月 女 91 91
# 5 5 黄粲 女 95 90
#@ 多列排序,一个为升序,一个为降序
df_new12 <- df[order(-df$数学成绩, df$语文成绩),]
df_new12
# 编号 姓名 性别 数学成绩 语文成绩
# 5 5 黄粲 女 95 90
# 6 6 赵月 女 91 91
# 7 7 朱忻 女 90 88
# 1 1 王明 男 90 91
# 2 2 李磊 男 88 75
# 8 8 陈振 男 81 77
# 3 3 张乐 男 80 83
# 9 9 武琳 女 80 85
# 10 10 孙晔 女 76 90
# 4 4 刘能 男 70 89
#@ 多列都为降序排序
df_new13 <- df[order(-df$数学成绩, -df$语文成绩),]
df_new13
# 编号 姓名 性别 数学成绩 语文成绩
# 5 5 黄粲 女 95 90
# 6 6 赵月 女 91 91
# 1 1 王明 男 90 91
# 7 7 朱忻 女 90 88
# 2 2 李磊 男 88 75
# 8 8 陈振 男 81 77
# 9 9 武琳 女 80 85
# 3 3 张乐 男 80 83
# 10 10 孙晔 女 76 90
# 4 4 刘能 男 70 89
#### 6.1 数据框分离,其实就是获取数据框的子集问题,方法有很多
#@ 利用数据框行列位置索引获取新的数据集
df
# 编号 姓名 性别 数学成绩 语文成绩
# 1 1 王明 男 90 91
# 2 2 李磊 男 88 75
# 3 3 张乐 男 80 83
# 4 4 刘能 男 70 89
# 5 5 黄粲 女 95 90
# 6 6 赵月 女 91 91
# 7 7 朱忻 女 90 88
# 8 8 陈振 男 81 77
# 9 9 武琳 女 80 85
# 10 10 孙晔 女 76 90
df_new14 <- df[,1:3]
df_new14
# 编号 姓名 性别
# 1 1 王明 男
# 2 2 李磊 男
# 3 3 张乐 男
# 4 4 刘能 男
# 5 5 黄粲 女
# 6 6 赵月 女
# 7 7 朱忻 女
# 8 8 陈振 男
# 9 9 武琳 女
# 10 10 孙晔 女
df_new15 <- df[2:5,]
df_new15
# 编号 姓名 性别 数学成绩 语文成绩
# 2 2 李磊 男 88 75
# 3 3 张乐 男 80 83
# 4 4 刘能 男 70 89
# 5 5 黄粲 女 95 90
#### 6.2 根据数据框的行名和列名进行子集的提取
#@ 根据行名进行提取数据框子集,为了方便识别,我们重新定义一个数据框df的行名
row.names(df) <- df$姓名
df
# 编号 姓名 性别 数学成绩 语文成绩
# 王明 1 王明 男 90 91
# 李磊 2 李磊 男 88 75
# 张乐 3 张乐 男 80 83
# 刘能 4 刘能 男 70 89
# 黄粲 5 黄粲 女 95 90
# 赵月 6 赵月 女 91 91
# 朱忻 7 朱忻 女 90 88
# 陈振 8 陈振 男 81 77
# 武琳 9 武琳 女 80 85
# 孙晔 10 孙晔 女 76 90
df_new16 <- df[c("王明", "赵月", "孙晔"),]
df_new16
# 编号 姓名 性别 数学成绩 语文成绩
# 王明 1 王明 男 90 91
# 赵月 6 赵月 女 91 91
# 孙晔 10 孙晔 女 76 90
#@ 根据列名进行数据框子集的提取
df_new17 <- df[,c("数学成绩", "语文成绩")]
df_new17
# 数学成绩 语文成绩
# 王明 90 91
# 李磊 88 75
# 张乐 80 83
# 刘能 70 89
# 黄粲 95 90
# 赵月 91 91
# 朱忻 90 88
# 陈振 81 77
# 武琳 80 85
# 孙晔 76 90
df_new18 <- df[c("王明", "赵月", "孙晔"), c("数学成绩", "语文成绩")]
df_new18
# 数学成绩 语文成绩
# 王明 90 91
# 赵月 91 91
# 孙晔 76 90
#### 6.3 subset函数提取数据框子集
df_new19 <- subset(df, select = 数学成绩)
df_new19
# 数学成绩
# 王明 90
# 李磊 88
# 张乐 80
# 刘能 70
# 黄粲 95
# 赵月 91
# 朱忻 90
# 陈振 81
# 武琳 80
# 孙晔 76
#@ 根据列名范围进行筛选
df_new20 <- subset(df, select = 数学成绩:语文成绩)
df_new20
# 数学成绩 语文成绩
# 王明 90 91
# 李磊 88 75
# 张乐 80 83
# 刘能 70 89
# 黄粲 95 90
# 赵月 91 91
# 朱忻 90 88
# 陈振 81 77
# 武琳 80 85
# 孙晔 76 90
#@ 有条件的筛选某一列数据
df_new21 <- subset(df, 数学成绩> 80, select = 语文成绩)
df_new21
# 语文成绩
# 王明 91
# 李磊 75
# 黄粲 90
# 赵月 91
# 朱忻 88
# 陈振 77
#### 6.4 dplyr包中的%in%和select()函数
df_new22 <- dplyr::select(df,数学成绩)
df_new22
# 数学成绩
# 王明 90
# 李磊 88
# 张乐 80
# 刘能 70
# 黄粲 95
# 赵月 91
# 朱忻 90
# 陈振 81
# 武琳 80
# 孙晔 76
df_new23 <- dplyr::select(df, 数学成绩, 语文成绩)
df_new23
# 数学成绩 语文成绩
# 王明 90 91
# 李磊 88 75
# 张乐 80 83
# 刘能 70 89
# 黄粲 95 90
# 赵月 91 91
# 朱忻 90 88
# 陈振 81 77
# 武琳 80 85
# 孙晔 76 90
#### 6.5 数据框的合并方法也有很多
#@ 按列进行合并,行数必须相同
df_new24 <- cbind(df_new13, df_new14)
df_new24
# 编号 姓名 性别 数学成绩 语文成绩 编号 姓名 性别
# 5 5 黄粲 女 95 90 1 王明 男
# 6 6 赵月 女 91 91 2 李磊 男
# 1 1 王明 男 90 91 3 张乐 男
# 7 7 朱忻 女 90 88 4 刘能 男
# 2 2 李磊 男 88 75 5 黄粲 女
# 8 8 陈振 男 81 77 6 赵月 女
# 9 9 武琳 女 80 85 7 朱忻 女
# 3 3 张乐 男 80 83 8 陈振 男
# 10 10 孙晔 女 76 90 9 武琳 女
# 4 4 刘能 男 70 89 10 孙晔 女
#@ 按行进行合并,列数必须相同
df_new25 <- rbind(df_new18, df_new20)
df_new25
# 数学成绩 语文成绩
# 王明 90 91
# 赵月 91 91
# 孙晔 76 90
# 王明1 90 91
# 李磊 88 75
# 张乐 80 83
# 刘能 70 89
# 黄粲 95 90
# 赵月1 91 91
# 朱忻 90 88
# 陈振 81 77
# 武琳 80 85
# 孙晔1 76 90
#@ merge合并,两个数据框根据相同的列进行合并:merge(),merge.data.frame()
#@ 主要参数有by.x,by.y和all.x,all.y和all,设置合理就会得到你想要的结果,不合理的话可能啥也没有
df_new26 <- merge(x = df_new2, y = df_new5, by.x = "姓名", by.y = "姓名", all = T)
df_new26
# 姓名 编号.x 性别.x 数学成绩.x 语文成绩.x 编号.y 性别.y
# 1 陈振 NA
# 2 黄粲 5 女 95 90 5 女
# 3 李磊 NA
# 4 孙晔 10 女 76 90 NA
# 5 王明 NA
# 6 武琳 9 女 80 85 NA
# 7 赵月 6 女 91 91 6 女
# 8 朱忻 7 女 90 88 7 女
# 数学成绩.y 语文成绩.y
# 1 81 77
# 2 95 90
# 3 88 75
# 4 NA NA
# 5 90 91
# 6 NA NA
# 7 91 91
# 8 90 88
df_t <- t(df)
df_t
# [,1] [,2] [,3] [,4] [,5] [,6] [,7]
# 编号 " 1" " 2" " 3" " 4" " 5" " 6" " 7"
# 姓名 "王明" "李磊" "张乐" "刘能" "黄粲" "赵月" "朱忻"
# 性别 "男" "男" "男" "男" "女" "女" "女"
# 数学成绩 "90" "88" "80" "70" "95" "91" "90"
# 语文成绩 "91" "75" "83" "89" "90" "91" "88"
# [,8] [,9] [,10]
# 编号 " 8" " 9" "10"
# 姓名 "陈振" "武琳" "孙晔"
# 性别 "男" "女" "女"
# 数学成绩 "81" "80" "76"
# 语文成绩 "77" "85" "90"
#@ 转置之后的数据结构类型发生了变化
class(df_t)
# [1] "matrix"
#@ 且无法强制转换
df_t_new < -as.data.frame(t(df))
# 错误: 找不到对象'df_t_new'
#### 8.1 删除数据框某一列或多列
df
# 编号 姓名 性别 数学成绩 语文成绩
# 王明 1 王明 男 90 91
# 李磊 2 李磊 男 88 75
# 张乐 3 张乐 男 80 83
# 刘能 4 刘能 男 70 89
# 黄粲 5 黄粲 女 95 90
# 赵月 6 赵月 女 91 91
# 朱忻 7 朱忻 女 90 88
# 陈振 8 陈振 男 81 77
# 武琳 9 武琳 女 80 85
# 孙晔 10 孙晔 女 76 90
dim(df)
# [1] 10 5
df_new1
# 编号 姓名 性别 数学成绩 语文成绩
# 1 1 王明 男 90 91
# 2 2 李磊 男 88 75
# 3 3 张乐 男 80 83
# 4 4 刘能 男 70 89
# 8 8 陈振 男 81 77
df_new1$编号 <- NULL
df_new1
# 姓名 性别 数学成绩 语文成绩
# 1 王明 男 90 91
# 2 李磊 男 88 75
# 3 张乐 男 80 83
# 4 刘能 男 70 89
# 8 陈振 男 81 77
df_new1[,2:4] <- NULL
df_new1
# 姓名
# 1 王明
# 2 李磊
# 3 张乐
# 4 刘能
# 8 陈振
#### 8.2 删除数据框某一行或多行
df_new2
# 编号 姓名 性别 数学成绩 语文成绩
# 5 5 黄粲 女 95 90
# 6 6 赵月 女 91 91
# 7 7 朱忻 女 90 88
# 9 9 武琳 女 80 85
# 10 10 孙晔 女 76 90
df_new2[1,] <- NULL
# Error in x[[jj]][iseq] <- vjj : 更换参数长度为零
df_new2[1,] <- ""
# Warning messages:
# 1: In `[<-.factor`(`*tmp*`, iseq, value = "") :
# invalid factor level, NA generated
# 2: In `[<-.factor`(`*tmp*`, iseq, value = "") :
# invalid factor level, NA generated
# 3: In `[<-.factor`(`*tmp*`, iseq, value = "") :
# invalid factor level, NA generated
# 4: In `[<-.factor`(`*tmp*`, iseq, value = "") :
# invalid factor level, NA generated
df_new2
# 编号 姓名 性别 数学成绩 语文成绩
# 5
# 6 6 赵月 女 91 91
# 7 7 朱忻 女 90 88
# 9 9 武琳 女 80 85
# 10 10 孙晔 女 76 90
df_new27 <- df_new2[-c(1),] # 用c()和-的组合,可以很轻松的删除你不想要的行
df_new27
# 编号 姓名 性别 数学成绩 语文成绩
# 6 6 赵月 女 91 91
# 7 7 朱忻 女 90 88
# 9 9 武琳 女 80 85
# 10 10 孙晔 女 76 90
df_new3
# 数学成绩 语文成绩
# 1 90 91
# 2 88 75
# 3 80 83
# 4 70 89
# 5 95 90
# 6 91 91
# 7 90 88
# 8 81 77
# 9 80 85
# 10 76 90
df_new28 <- df_new3[-c(1,3,5,7), ] #删除掉1/3/5/7行
df_new28
# 数学成绩 语文成绩
# 2 88 75
# 4 70 89
# 6 91 91
# 8 81 77
# 9 80 85
# 10 76 90
df_new29 <- df_new3[-c(1:3),] # 也可以指定行的范围进行删除
df_new29
# 数学成绩 语文成绩
# 4 70 89
# 5 95 90
# 6 91 91
# 7 90 88
# 8 81 77
# 9 80 85
# 10 76 90
#### 8.3 替换数据框中的缺失值为0
#@ 咱们先构建一个含有缺失值的数据框
set.seed(110)
m <- matrix(sample(c(NA, 1:10), 100, replace = TRUE), 10)
mydf <- as.data.frame(m)
mydf
# V1 V2 V3 V4 V5 V6 V7 V8 V9 V10
# 1 3 2 4 10 NA 8 NA 7 6 9
# 2 7 2 8 4 4 8 5 6 9 8
# 3 5 9 9 6 8 6 2 3 6 2
# 4 2 9 5 7 5 4 7 7 9 4
# 5 8 NA 9 10 5 4 5 9 2 9
# 6 6 9 6 9 7 3 7 10 1 10
# 7 2 NA 1 3 1 2 7 4 2 5
# 8 8 4 10 NA 3 10 9 9 5 6
# 9 10 6 2 NA 1 5 2 2 9 9
# 10 3 8 8 7 5 2 5 8 7 7
is.na(mydf) # is.na()函数返回数据类型是否是缺失值的真假值
# V1 V2 V3 V4 V5 V6 V7 V8 V9
# [1,] FALSE FALSE FALSE FALSE TRUE FALSE TRUE FALSE FALSE
# [2,] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
# [3,] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
# [4,] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
# [5,] FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
# [6,] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
# [7,] FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
# [8,] FALSE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE
# [9,] FALSE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE
# [10,] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
# V10
# [1,] FALSE
# [2,] FALSE
# [3,] FALSE
# [4,] FALSE
# [5,] FALSE
# [6,] FALSE
# [7,] FALSE
# [8,] FALSE
# [9,] FALSE
# [10,] FALSE
mydf[is.na(mydf)] <- 0 # 然后数据框根据真假值进行替换0,为真的替换为0,为真就是NA
mydf
# V1 V2 V3 V4 V5 V6 V7 V8 V9 V10
# 1 3 2 4 10 0 8 0 7 6 9
# 2 7 2 8 4 4 8 5 6 9 8
# 3 5 9 9 6 8 6 2 3 6 2
# 4 2 9 5 7 5 4 7 7 9 4
# 5 8 0 9 10 5 4 5 9 2 9
# 6 6 9 6 9 7 3 7 10 1 10
# 7 2 0 1 3 1 2 7 4 2 5
# 8 8 4 10 0 3 10 9 9 5 6
# 9 10 6 2 0 1 5 2 2 9 9
# 10 3 8 8 7 5 2 5 8 7 7
#### 8.4 根据某个元素进行删除行或列
set.seed(110)
mydf2 <- as.data.frame(matrix(sample(c(NA, 1:20), 100, replace = TRUE), 10))
mydf2
# V1 V2 V3 V4 V5 V6 V7 V8 V9 V10
# 1 19 18 11 10 7 19 5 9 2 1
# 2 5 9 13 9 1 2 7 15 20 NA
# 3 18 NA 17 3 3 18 6 2 5 4
# 4 8 NA 13 16 1 NA 3 1 6 4
# 5 15 20 2 16 5 5 7 2 11 7
# 6 6 6 13 NA 13 18 4 5 7 9
# 7 2 20 8 4 8 7 12 11 7 15
# 8 8 8 11 8 6 14 2 12 18 19
# 9 3 11 20 5 20 9 8 8 17 4
# 10 18 9 6 5 4 18 15 11 9 18
#@ 根据某个元素删除行,例如这个元素是NA
mydf2 <- mydf2[complete.cases(mydf2),]
mydf2
# V1 V2 V3 V4 V5 V6 V7 V8 V9 V10
# 1 19 18 11 10 7 19 5 9 2 1
# 5 15 20 2 16 5 5 7 2 11 7
# 7 2 20 8 4 8 7 12 11 7 15
# 8 8 8 11 8 6 14 2 12 18 19
# 9 3 11 20 5 20 9 8 8 17 4
# 10 18 9 6 5 4 18 15 11 9 18
?complete.cases
# Find Complete Cases
# Return a logical vector indicating which cases are complete, i.e., have no missing values.
set.seed(110)
mydf3 <- as.data.frame(matrix(sample(c(NA, 1:10), 100, replace = TRUE), 10))
mydf3
# V1 V2 V3 V4 V5 V6 V7 V8 V9 V10
# 1 3 2 4 10 NA 8 NA 7 6 9
# 2 7 2 8 4 4 8 5 6 9 8
# 3 5 9 9 6 8 6 2 3 6 2
# 4 2 9 5 7 5 4 7 7 9 4
# 5 8 NA 9 10 5 4 5 9 2 9
# 6 6 9 6 9 7 3 7 10 1 10
# 7 2 NA 1 3 1 2 7 4 2 5
# 8 8 4 10 NA 3 10 9 9 5 6
# 9 10 6 2 NA 1 5 2 2 9 9
# 10 3 8 8 7 5 2 5 8 7 7
mydf3 <- na.omit(mydf3)
mydf3
# V1 V2 V3 V4 V5 V6 V7 V8 V9 V10
# 2 7 2 8 4 4 8 5 6 9 8
# 3 5 9 9 6 8 6 2 3 6 2
# 4 2 9 5 7 5 4 7 7 9 4
# 6 6 9 6 9 7 3 7 10 1 10
# 10 3 8 8 7 5 2 5 8 7 7
?na.omit
# Handle Missing Values in Objects
#@ 根据某个元素删除列,例如这个元素是NA
set.seed(110)
mydf4 <- as.data.frame(matrix(sample(c(NA, 1:30), 100, replace = TRUE), 10))
mydf4
# V1 V2 V3 V4 V5 V6 V7 V8 V9 V10
# 1 19 3 27 11 8 16 3 4 14 7
# 2 23 18 27 30 26 23 1 19 21 25
# 3 5 18 6 22 11 NA 5 2 23 26
# 4 18 30 24 13 20 4 27 26 23 4
# 5 8 25 20 17 6 8 13 21 9 12
# 6 15 9 8 26 23 29 29 18 18 25
# 7 6 NA 11 13 10 5 8 NA 5 2
# 8 2 25 25 2 9 5 24 5 7 8
# 9 8 NA 21 13 3 7 6 18 6 28
# 10 26 20 9 28 16 1 20 7 3 15
is.na(mydf4)
# V1 V2 V3 V4 V5 V6 V7 V8 V9
# [1,] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
# [2,] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
# [3,] FALSE FALSE FALSE FALSE FALSE TRUE FALSE FALSE FALSE
# [4,] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
# [5,] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
# [6,] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
# [7,] FALSE TRUE FALSE FALSE FALSE FALSE FALSE TRUE FALSE
# [8,] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
# [9,] FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
# [10,] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
# V10
# [1,] FALSE
# [2,] FALSE
# [3,] FALSE
# [4,] FALSE
# [5,] FALSE
# [6,] FALSE
# [7,] FALSE
# [8,] FALSE
# [9,] FALSE
# [10,] FALSE
na_flag <- apply(is.na(mydf4), 2, sum)
mydf4 <- mydf4[,which(na_flag == 0)]
mydf4
# V1 V3 V4 V5 V7 V9 V10
# 1 19 27 11 8 3 14 7
# 2 23 27 30 26 1 21 25
# 3 5 6 22 11 5 23 26
# 4 18 24 13 20 27 23 4
# 5 8 20 17 6 13 9 12
# 6 15 8 26 23 29 18 25
# 7 6 11 13 10 8 5 2
# 8 2 25 2 9 24 7 8
# 9 8 21 13 3 6 6 28
# 10 26 9 28 16 20 3 15
sessionInfo()
# R version 3.6.2 (2019-12-12)
# Platform: x86_64-w64-mingw32/x64 (64-bit)
# Running under: Windows 10 x64 (build 18363)
#
# Matrix products: default
#
# locale:
# [1] LC_COLLATE=Chinese (Simplified)_China.936
# [2] LC_CTYPE=Chinese (Simplified)_China.936
# [3] LC_MONETARY=Chinese (Simplified)_China.936
# [4] LC_NUMERIC=C
# [5] LC_TIME=Chinese (Simplified)_China.936
#
# attached base packages:
# [1] stats graphics grDevices utils datasets
# [6] methods base
#
# other attached packages:
# [1] chron_2.3-54 sqldf_0.4-11 RSQLite_2.1.5 gsubfn_0.7
# [5] proto_1.0.0
#
# loaded via a namespace (and not attached):
# [1] zip_2.0.4 Rcpp_1.0.3 cellranger_1.1.0
# [4] pillar_1.4.3 compiler_3.6.2 forcats_0.4.0
# [7] tools_3.6.2 zeallot_0.1.0 digest_0.6.23
# [10] packrat_0.5.0 bit_1.1-14 memoise_1.1.0
# [13] tibble_2.1.3 pkgconfig_2.0.3 rlang_0.4.2
# [16] openxlsx_4.1.4 DBI_1.1.0 rstudioapi_0.10
# [19] curl_4.3 haven_2.2.0 rio_0.5.16
# [22] dplyr_0.8.3 vctrs_0.2.1 hms_0.5.2
# [25] tidyselect_0.2.5 bit64_0.9-7 glue_1.3.1
# [28] data.table_1.12.8 R6_2.4.1 tcltk_3.6.2
# [31] readxl_1.3.1 foreign_0.8-72 purrr_0.3.3
# [34] blob_1.2.0 magrittr_1.5 backports_1.1.5
# [37] assertthat_0.2.1 stringi_1.4.3 crayon_1.3.4