目录
(3)使用read.table()或read.csv()读取文本文件,返回数据框
(2)用row.names、rownames函数查看行名、修改行名
(2)使用cbind横向连接(column bind,列更多了)
1.创建数据框
(1)使用已有向量创建数据框
ID <- c(LETTERS[1:5])
Name <- c('李小明', '张友谊', '王大龙', '沈小霞', '钱多多')
Gender <- c('男', '男', '女', '男', '女')
Age <- c(18, 20, 19, 21, 17)
df1 <- data.frame(ID, Name, Gender, Age)
df1
## ID Name Gender Age
## 1 A 李小明 男 18
## 2 B 张友谊 男 20
## 3 C 王大龙 女 19
## 4 D 沈小霞 男 21
## 5 E 钱多多 女 17
(2)使用向量直接创建数据框
df2 <-data.frame(
ID=c(11,12,13),
Name=c("小明","小丽","小红"),
Gender=c(T,T,F),
Birthdate=c("2004-12-29","2003-5-6","2002-8-8")
)
df2
## ID Name Gender Birthdate
## 1 11 小明 TRUE 2004-12-29
## 2 12 小丽 TRUE 2003-5-6
## 3 13 小红 FALSE 2002-8-8
# 使用row.names参数直接为行命名
df2 <-data.frame(
ID=c(11,12,13),
Name=c("小明","小丽","小红"),
Gender=c(T,T,F),
Birthdate=c("2004-12-29","2003-5-6","2002-8-8"),
row.names=paste('row', 1:3)
)
df2
## ID Name Gender Birthdate
## row 1 11 小明 TRUE 2004-12-29
## row 2 12 小丽 TRUE 2003-5-6
## row 3 13 小红 FALSE 2002-8-8
(3)使用read.table()或read.csv()读取文本文件,返回数据框
df3 <- read.table('./Data/06/student.txt',encoding = 'UTF-8')
df3
## V1 V2 V3 V4
## 1 ID Name Gender Age
## 2 A 李小明 男 18
## 3 B 张友谊 男 20
## 4 C 王大龙 女 19
## 5 D 沈小霞 男 21
## 6 E 钱多多 女 17
class(df3)
## [1] "data.frame"
df3 <- read.table('./Data/06/student.txt',
header = T,
encoding = 'UTF-8')
df3
## ID Name Gender Age
## 1 A 李小明 男 18
## 2 B 张友谊 男 20
## 3 C 王大龙 女 19
## 4 D 沈小霞 男 21
## 5 E 钱多多 女 17
df3 <- read.table('./Data/06/student.txt',
header = T, # 包含标题
row.names = 1, # 第1列为行名
encoding = 'UTF-8')
df3
## Name Gender Age
## A 李小明 男 18
## B 张友谊 男 20
## C 王大龙 女 19
## D 沈小霞 男 21
## E 钱多多 女 17
(4)从内存中读取Excel、txt内容
# df4=read.table('clipboard',header=T)
# df4
2.数据框信息
(1)用names、colnames函数查看列名、修改列名
names(df1) # 返回列名
[1] "ID" "Name" "Gender" "Age"
colnames(df1) # 返回列名
[1] "ID" "Name" "Gender" "Age"
names(df1)[2] <- 'XingMing' # 修改列名
df1
## ID XingMing Gender Age
## 1 A 李小明 男 18
## 2 B 张友谊 男 20
## 3 C 王大龙 女 19
## 4 D 沈小霞 男 21
## 5 E 钱多多 女 17
names(df1)[2] <- 'Name' # 修改列名
df1
## ID Name Gender Age
## 1 A 李小明 男 18
## 2 B 张友谊 男 20
## 3 C 王大龙 女 19
## 4 D 沈小霞 男 21
## 5 E 钱多多 女 17
(2)用row.names、rownames函数查看行名、修改行名
rownames(df1) # 返回行名
## [1] "1" "2" "3" "4" "5"
row.names(df1) # 返回行名
## [1] "1" "2" "3" "4" "5"
rownames(df1) <- df1$ID # 修改行名
dimnames(df1) # 查看行名和列名
## [[1]]
## [1] "A" "B" "C" "D" "E"## [[2]]
## [1] "ID" "XingMing" "Gender" "Age"
(3)获取行列维度的函数
nrow(df1) # 返回行数
## [1] 5
ncol(df1) # 返回列数
## [1] 4
dim(df1) # 返回行列数
## [1] 5 4
(4)获取数据框的结构信息
str(df1)
## 'data.frame': 5 obs. of 4 variables:
## $ ID : chr "A" "B" "C" "D" ...
## $ Name : chr "李小明" "张友谊" "王大龙" "沈小霞" ...
## $ Gender: chr "男" "男" "女" "男" ...
## $ Age : num 18 20 19 21 17
(5)显示数据框前几行信息
head(df1, 3) # 返回前3行数据
## ID Name Gender Age
## A A 李小明 男 18
## B B 张友谊 男 20
## C C 王大龙 女 19
tail(df1, 3) # 返回后3行数据
## ID Name Gender Age
## C C 王大龙 女 19
## D D 沈小霞 男 21
## E E 钱多多 女 17
3.访问元素
(1)访问某行,从1计数
df1[2,]
## ID Name Gender Age
## B B 张友谊 男 20
df1['B',]
## ID Name Gender Age
## B B 张友谊 男 20
class(df1[2,]) # 访问某行,返回数据框
## [1] "data.frame"
class(df1['B',]) # 访问某行,返回数据框
## [1] "data.frame"
(2)访问某列,从1计数
A.返回数据框
df1[2] # 访问第2列,返回数据框
## Name
## A 李小明
## B 张友谊
## C 王大龙
## D 沈小霞
## E 钱多多
df1['Name'] # 访问第2列,返回数据框
## Name
## A 李小明
## B 张友谊
## C 王大龙
## D 沈小霞
## E 钱多多
class(df1[2]) # 访问某列,返回数据框
## [1] "data.frame"
class(df1['Name']) # 访问某列,返回数据框
## [1] "data.frame"
B.返回元素值的类型
df1[, 2] # 访问第2列,返回元素值的类型
## [1] "李小明" "张友谊" "王大龙" "沈小霞" "钱多多"
df1[[2]] # 等价写法:双中括号编号
## [1] "李小明" "张友谊" "王大龙" "沈小霞" "钱多多"
df1[['Name']] # 等价写法:双中括号列名
## [1] "李小明" "张友谊" "王大龙" "沈小霞" "钱多多"
df1$Name # 等价写法:$符号
## [1] "李小明" "张友谊" "王大龙" "沈小霞" "钱多多"
class(df1[, 2]) # 访问某列,返回元素值的类型(字符型)
## [1] "character"
class(df1[, 4]) # 访问某列,返回元素值的类型(数值型)
## [1] "numeric"
(3)访问某个字段值
df1[3, 2]
## [1] "王大龙"
df1['C', 'Name']
## [1] "王大龙"
df1[3, ]$Name
## [1] "王大龙"
df1['C', ]$Name
## [1] "王大龙"
df1[3, 'Name']
## [1] "王大龙"
df1['C', 2]
## [1] "王大龙"
(4)访问多列,返回数据框
A.连续多列
df1[, 2:4] # 访问2-4列
## Name Gender Age
## A 李小明 男 18
## B 张友谊 男 20
## C 王大龙 女 19
## D 沈小霞 男 21
## E 钱多多 女 17
df1[2:4] # 访问2-4列
## Name Gender Age
## A 李小明 男 18
## B 张友谊 男 20
## C 王大龙 女 19
## D 沈小霞 男 21
## E 钱多多 女 17
df1[,c(2:4)] # 访问2-4列,不建议省略逗号,防止误解
## Name Gender Age
## A 李小明 男 18
## B 张友谊 男 20
## C 王大龙 女 19
## D 沈小霞 男 21
## E 钱多多 女 17
B.不连续多列
df1[, c(2, 4)]
## Name Age
## A 李小明 18
## B 张友谊 20
## C 王大龙 19
## D 沈小霞 21
## E 钱多多 17
df1[, c('Name', 'Age')]
## Name Age
## A 李小明 18
## B 张友谊 20
## C 王大龙 19
## D 沈小霞 21
## E 钱多多 17
df1[c(2, 4)] # 不建议省略逗号,防止误解
## Name Age
## A 李小明 18
## B 张友谊 20
## C 王大龙 19
## D 沈小霞 21
## E 钱多多 17
df1[c('Name', 'Age')] # 不建议省略逗号,防止误解
## Name Age
## A 李小明 18
## B 张友谊 20
## C 王大龙 19
## D 沈小霞 21
## E 钱多多 17
class(df1[c(2, 4)]) # 返回数据框
## [1] "data.frame"
class(df1[c('Name', 'Age')]) # 返回数据框
## [1] "data.frame"
(5)访问多行, 返回数据框
A.连续多行
df1[2:4,]
## ID Name Gender Age
## B B 张友谊 男 20
## C C 王大龙 女 19
## D D 沈小霞 男 21
df1[c(2:4),]
## ID Name Gender Age
## B B 张友谊 男 20
## C C 王大龙 女 19
## D D 沈小霞 男 21
class(df1[2:4, ]) # 返回数据框
## [1] "data.frame"
B.不连续多行
df1[c(2, 4),]
## ID Name Gender Age
## B B 张友谊 男 20
## D D 沈小霞 男 21
df1[c('B', 'D'),]
## ID Name Gender Age
## B B 张友谊 男 20
## D D 沈小霞 男 21
class(df1[c(2, 4),]) # 返回数据框
## [1] "data.frame"
class(df1[c('B', 'D'),]) # 返回数据框
## [1] "data.frame"
(6)查询与子集
A.布尔向量,配合which函数,实现选择运算
df1
## ID Name Gender Age
## A A 李小明 男 18
## B B 张友谊 男 20
## C C 王大龙 女 19
## D D 沈小霞 男 21
## E E 钱多多 女 17
df1$Gender
## [1] "男" "男" "女" "男" "女"
df1$Gender == '男'
## [1] TRUE TRUE FALSE TRUE FALSE
which(df1$Gender == '男')
## [1] 1 2 4
df1[which(df1$Gender == '男'),] # 访问所有性别为男记录
## ID Name Gender Age
## A A 李小明 男 18
## B B 张友谊 男 20
## D D 沈小霞 男 21
df1[which(df1$Age > 18), c('Name', 'Gender', 'Age')] # 返回数据框
## Name Gender Age
## B 张友谊 男 20
## C 王大龙 女 19
## D 沈小霞 男 21
df1[which(df1$Age > 18), 'Age'] # 返回元素的值
## [1] 20 19 21
B.which函数增加逻辑运算
df1[which(df1$Gender == '男' & df1$Age > 19), 'Name']
## [1] "张友谊" "沈小霞"
df1[which(df1$Age < 18| df1$Age >20), ]
## ID Name Gender Age
## 4 D 沈小霞 男 21
## 5 E 钱多多 女 17
(7)subset函数过滤
df1
## ID Name Gender Age
## A A 李小明 男 18
## B B 张友谊 男 20
## C C 王大龙 女 19
## D D 沈小霞 男 21
## E E 钱多多 女 17
subset(df1, Gender == '男' & Age > 19, 'Name')
## Name
## 2 张友谊
## 4 沈小霞
subset(df1, Gender == '男' & Age > 19, c('Name', 'Age'))
## Name Age
## 2 张友谊 20
## 4 沈小霞 21
subset(df1, Gender == '男' & Age > 19, )
## ID Name Gender Age
## 2 B 张友谊 男 20
## 4 D 沈小霞 男 21
subset(df1, Age < 18 | Age > 20, )
## ID Name Gender Age
## 4 D 沈小霞 男 21
## 5 E 钱多多 女 17
subset(df1, !(Age < 18 | Age > 20), )
## ID Name Gender Age
## 1 A 李小明 男 18
## 2 B 张友谊 男 20
## 3 C 王大龙 女 19
(8)使用SQL查询语句
library(sqldf)
sqldf('select * from df1')
## ID Name Gender Age
## 1 A 李小明 男 18
## 2 B 张友谊 男 20
## 3 C 王大龙 女 19
## 4 D 沈小霞 男 21
## 5 E 钱多多 女 17
例:查询df1中年龄大于20或小于18的行。
sqldf('select * from df1 where Age > 20 or Age < 18')
## ID Name Gender Age
## 1 D 沈小霞 男 21
## 2 E 钱多多 女 17
例:查询df1中性别为男且年龄大于18的行。
sqldf('select * from df1 where Gender == "男"and Age > 18')
## ID Name Gender Age
## 1 B 张友谊 男 20
## 2 D 沈小霞 男 21
(9)遍历数据框(时间复杂度高)
dim(df1)
## [1] 5 4
dim(df1)[1]
## [1] 5
dim(df1)[2]
## [1] 4
# 获取数据框维度
x <- dim(df1)[1]
y <- dim(df1)[2]
# 遍历数据框中每个值
for(i in 1:x){
for(j in 1:y){
print(df1[i, j])
}
}
## [1] "A"
## [1] "李小明"
## [1] "男"
## [1] 18
## [1] "B"
## [1] "张友谊"
## [1] "男"
## [1] 20
## [1] "C"
## [1] "王大龙"
## [1] "女"
## [1] 19
## [1] "D"
## [1] "沈小霞"
## [1] "男"
## [1] 21
## [1] "E"
## [1] "钱多多"
## [1] "女"
## [1] 17
for(i in 1:x){
if(df1[i, 'Age'] > 18){
print(df1[i,])
}
}
## ID Name Gender Age
## B B 张友谊 男 20
## ID Name Gender Age
## C C 王大龙 女 19
## ID Name Gender Age
## D D 沈小霞 男 21
(10)使用table函数获得统计量
table(df1$Gender)
##
## 男 女
## 3 2
table(df1$Age)
##
## 17 18 19 20 21
## 1 1 1 1 1
table(df1$Gender, df1$Age)
## 17 18 19 20 21
## 男 0 1 0 1 1
## 女 1 0 1 0 0
4.修改数据框
(1)查看和修改数据类型
str(df1)
## 'data.frame': 5 obs. of 4 variables:
## $ ID : chr "A" "B" "C" "D" ...
## $ Name : chr "李小明" "张友谊" "王大龙" "沈小霞" ...
## $ Gender: chr "男" "男" "女" "男" ...
## $ Age : num 18 20 19 21 17
df1$Gender <- as.factor(df1$Gender)
str(df1)
## 'data.frame': 5 obs. of 4 variables:
## $ ID : chr "A" "B" "C" "D" ...
## $ Name : chr "李小明" "张友谊" "王大龙" "沈小霞" ...
## $ Gender: Factor w/ 2 levels "男","女": 1 1 2 1 2
## $ Age : num 18 20 19 21 17
(2)增加新列
df1$Edu <- c('本科', '专科', '研究生', '本科', '研究生')
df1
ID Name Gender Age Edu
## 1 A 李小明 男 18 本科
## 2 B 张友谊 男 20 专科
## 3 C 王大龙 女 19 研究生
## 4 D 沈小霞 男 21 本科
## 5 E 钱多多 女 17 研究生
df2 <- cbind(df1, Age4=c(1, 3, 4, 5, 6))
df2
## ID Name Gender Age Edu Age4
## 1 A 李小明 男 18 本科 1
## 2 B 张友谊 男 20 专科 3
## 3 C 王大龙 女 19 研究生 4
## 4 D 沈小霞 男 21 本科 5
## 5 E 钱多多 女 17 研究生 6
(3)删除列
subset(df2, select = -Age4) # 删除Age4列
ID Name Gender Age Edu
## 1 A 李小明 男 18 本科
## 2 B 张友谊 男 20 专科
## 3 C 王大龙 女 19 研究生
## 4 D 沈小霞 男 21 本科
## 5 E 钱多多 女 17 研究生
df2[, -6] # 删除第6列
ID Name Gender Age Edu
## 1 A 李小明 男 18 本科
## 2 B 张友谊 男 20 专科
## 3 C 王大龙 女 19 研究生
## 4 D 沈小霞 男 21 本科
## 5 E 钱多多 女 17 研究生
ColNum <- dim(df2)[2]
df2[, -ColNum]
ID Name Gender Age Edu
## 1 A 李小明 男 18 本科
## 2 B 张友谊 男 20 专科
## 3 C 王大龙 女 19 研究生
## 4 D 沈小霞 男 21 本科
## 5 E 钱多多 女 17 研究生
(4)删除行
df2[-1, ]
## ID Name Gender Age Edu Age4
## 2 B 张友谊 男 20 专科 3
## 3 C 王大龙 女 19 研究生 4
## 4 D 沈小霞 男 21 本科 5
## 5 E 钱多多 女 17 研究生 6
which(df2$Gender == '男')
## [1] 1 2 4
df2[-which(df2$Gender == '男'),]
## ID Name Gender Age Edu Age4
## 3 C 王大龙 女 19 研究生 4
## 5 E 钱多多 女 17 研究生 6
5.连接数据框、拆分数据框
(1)使用merge函数横向连接
score <- data.frame(
ID = c('A', 'C', 'B', 'C', 'E', 'C', 'A'),
course = c('数学', '数学', '数学', '语文', '数学', '英语', '英语'),
score = c(69, 80, 55, 90, 93, 77, 83)
)
score
## ID course score
## 1 A 数学 69
## 2 C 数学 80
## 3 B 数学 55
## 4 C 语文 90
## 5 E 数学 93
## 6 C 英语 77
## 7 A 英语 83
df1
## ID Name Gender Age Edu
## 1 A 李小明 男 18 本科
## 2 B 张友谊 男 20 专科
## 3 C 王大龙 女 19 研究生
## 4 D 沈小霞 男 21 本科
## 5 E 钱多多 女 17 研究生
merge(df1, score, by = 'ID')
## ID Name Gender Age Edu course score
## 1 A 李小明 男 18 本科 数学 69
## 2 A 李小明 男 18 本科 英语 83
## 3 B 张友谊 男 20 专科 数学 55
## 4 C 王大龙 女 19 研究生 数学 80
## 5 C 王大龙 女 19 研究生 语文 90
## 6 C 王大龙 女 19 研究生 英语 77
## 7 E 钱多多 女 17 研究生 数学 93
merge(x = df1, y = score, by.x = "ID", by.y = "ID")
## ID Name Gender Age Edu course score
## 1 A 李小明 男 18 本科 数学 69
## 2 A 李小明 男 18 本科 英语 83
## 3 B 张友谊 男 20 专科 数学 55
## 4 C 王大龙 女 19 研究生 数学 80
## 5 C 王大龙 女 19 研究生 语文 90
## 6 C 王大龙 女 19 研究生 英语 77
## 7 E 钱多多 女 17 研究生 数学 93
(2)使用cbind横向连接(column bind,列更多了)
# cbind(df1, score)
cbind(df1, score[1:5, ]) # 行数必须相同,没有外键关联
## ID Name Gender Age Edu ID course score
## 1 A 李小明 男 18 本科 A 数学 69
## 2 B 张友谊 男 20 专科 C 数学 80
## 3 C 王大龙 女 19 研究生 B 数学 55
## 4 D 沈小霞 男 21 本科 C 语文 90
## 5 E 钱多多 女 17 研究生 E 数学 93
(3)使用rbind纵向连接(row bind,行更多了)
stu1 <- data.frame(
姓名 = c('小丽', '小明'),
性别 = c('女', '男'),
班级 = c('1班', '1班')
)
stu2 <- data.frame(
姓名 = c('小美', '小红', '小艳'),
性别 = c('女', '男', '女'),
班级 = c('2班', '2班', '2班')
)
stu1
## 姓名 性别 班级
## 1 小丽 女 1班
## 2 小明 男 1班
stu2
## 姓名 性别 班级
## 1 小美 女 2班
## 2 小红 男 2班
## 3 小艳 女 2班
rbind(stu1, stu2) # 列数必须相同,列名要一致
## 姓名 性别 班级
## 1 小丽 女 1班
## 2 小明 男 1班
## 3 小美 女 2班
## 4 小红 男 2班
## 5 小艳 女 2班
(4)按照性别把df1拆成两个数据框
df1
## ID Name Gender Age Edu
## 1 A 李小明 男 18 本科
## 2 B 张友谊 男 20 专科
## 3 C 王大龙 女 19 研究生
## 4 D 沈小霞 男 21 本科
## 5 E 钱多多 女 17 研究生
A.方法1
df_T <- df1[df1$Gender == '男',]
df_F <- df1[df1$Gender == '女',]
df_T
## ID Name Gender Age Edu
## 1 A 李小明 男 18 本科
## 2 B 张友谊 男 20 专科
## 4 D 沈小霞 男 21 本科
df_F
## ID Name Gender Age Edu
## 3 C 王大龙 女 19 研究生
## 5 E 钱多多 女 17 研究生
A.方法2
df_sub <- split(df1, df1$Gender)
df_sub
## $男
## ID Name Gender Age Edu
## 1 A 李小明 男 18 本科
## 2 B 张友谊 男 20 专科
## 4 D 沈小霞 男 21 本科## $女
## ID Name Gender Age Edu
## 3 C 王大龙 女 19 研究生
## 5 E 钱多多 女 17 研究生
class(df_sub)
## [1] "list"
6.数据框的计算,按某列求平均值
result <- merge(x = df1, y = score, by = "ID")
result
## ID Name Gender Age Edu course score
## 1 A 李小明 男 18 本科 数学 69
## 2 A 李小明 男 18 本科 英语 83
## 3 B 张友谊 男 20 专科 数学 55
## 4 C 王大龙 女 19 研究生 数学 80
## 5 C 王大龙 女 19 研究生 语文 90
## 6 C 王大龙 女 19 研究生 英语 77
## 7 E 钱多多 女 17 研究生 数学 93
(1)求各科平均分、总分、选课人数
# 产生空白数据框
course_mean <- data.frame(course=c(), avg=c(), sum=c(), count=c())
for(i in unique(score$course)){
# 分组
subgrp <- score[which(score$course == i), 'score']
# 求行的平均数
count <- length(subgrp) # 计数
sum <- sum(subgrp) # 总分
avg <- mean(subgrp) # 平均分
# 合并到科目平均数
course_mean <- rbind(course_mean,
data.frame(course = c(i),
avg = c(avg),
sum = c(sum),
count = c(count)))
}
course_mean
## course avg sum count
## 1 数学 74.25 297 4
## 2 语文 90.00 90 1
## 3 英语 80.00 160 2
(2)求每个人的平均分
student_mean <- data.frame(student=c(), avg=c(), sum=c(), count=c())
for(i in unique(result$Name)){
# 分组
subgrp <- result[which(result$Name== i), 'score']
# 求行的平均数
count <- length(subgrp) # 计数
sum <- sum(subgrp) # 总分
avg <- mean(subgrp) # 平均分
# 合并到科目平均数
student_mean <- rbind(student_mean,
data.frame(student = c(i),
avg = c(avg),
sum = c(sum),
count = c(count)))
}
student_mean
## student avg sum count
## 1 李小明 76.00000 152 2
## 2 张友谊 55.00000 55 1
## 3 王大龙 82.33333 247 3
## 4 钱多多 93.00000 93 1
(3)使用tapply函数
result
## ID Name Gender Age Edu course score
## 1 A 李小明 男 18 本科 数学 69
## 2 A 李小明 男 18 本科 英语 83
## 3 B 张友谊 男 20 专科 数学 55
## 4 C 王大龙 女 19 研究生 数学 80
## 5 C 王大龙 女 19 研究生 语文 90
## 6 C 王大龙 女 19 研究生 英语 77
## 7 E 钱多多 女 17 研究生 数学 93
tapply(result[,7], result[,6],mean)
## 数学 英语 语文
## 74.25 80.00 90.00
tapply(result[,7], result[,6],sum)
## 数学 英语 语文
## 297 160 90
tapply(result[,7], result[,c(3,6)],mean)
## course
## Gender 数学 英语 语文
## 男 62.0 83 NA
## 女 86.5 77 90
tapply(result[,7], result[,c(2,6)],mean)
## course
## Name 数学 英语 语文
## 李小明 69 83 NA
## 钱多多 93 NA NA
## 王大龙 80 77 90
## 张友谊 55 NA NA
dat1 <- data.frame(host = c('A', 'A', 'A', 'E', 'E', 'G'),
guest = c('C', 'B', 'D', 'Q', 'F', 'W'),
num = c(2, 1, 2, 3, 0, 2))
dat1
## host guest num
## 1 A C 2
## 2 A B 1
## 3 A D 2
## 4 E Q 3
## 5 E F 0
## 6 G W 2
#tapply(vector, index, function)
tapply(dat1[, 3], dat1[, c(1, 2)], mean)
## guest
## host B C D F Q W
## A 1 2 2 NA NA NA
## E NA NA NA 0 3 NA
## G NA NA NA NA NA 2