目录
(3)使用DescTools包中的Freq函数生成频数分布表
(1)将短格式数据转化成长格式数据(数据框中有标识变量(类别因子))
一、读取和保存数据
1、读取外部数据
(1) 读取不含有标题的csv格式数据
table1_1 <- read.csv('./mydata/chap01/table1_1.csv', header = FALSE)
head(table1_1)
V1 V2 V3
1 性别 网购次数 满意度
2 女 6次以上 满意
3 男 3~5次 不满意
4 女 3~5次 不满意
5 男 3~5次 中立
6 女 1~2次 满意
(2) 读取含有标题的csv格式数据
table1_1 <- read.csv('./mydata/chap01/table1_1.csv')
head(table1_1)
性别 网购次数 满意度
1 女 6次以上 满意
2 男 3~5次 不满意
3 女 3~5次 不满意
4 男 3~5次 中立
5 女 1~2次 满意
6 男 6次以上 不满意
(3)读取R格式数据
load('./mydata/chap01/table1_1.RData')
2、保存数据
(1)将数据保存成csv格式
write.csv(table1_1, file='./mydata/chap01/table1_1_1.csv')
(2)将数据保存成R格式
save(table1_1, file='./mydata/chap01/table1_1.RData')
二、随机数和数据抽样
1、生成随机数
# 生成不同分布的随机数
rnorm(10) # 产生10个标准正态分布随机数
rnorm(10, 50, 5) # 产生10个均值为50,标准差为5的正态分布随机数
runif(10, 0, 100) # 在0~100之间产生10个均匀分布随机数
rchisq(10, 15) # 产生10个自由度为1.5的卡方分布随机数
# 想产生相同的随机数,使用set.seed()设定种子,如set.seed(10)
2、数据抽样
n <- 1:10
n1 <- sample(n, size=8) # 无放回抽取10个数据
n1
[1] 9 7 8 6 3 2 10 5
n2 <- sample(n, size=8, replace=TRUE) # 有放回抽取10个数据
n2
[1] 2 8 8 7 6 7 6 2
三、生成频数分布表
频数分布表:对类别数据(因子的水平)计数或数值数据类别化(分组)后计数生成的表格。
1、类别数据频数分布表
(1)一维列联表
# 读入数据【2000个消费者的网购情况调查数据】
data1_1 <- read.csv('./mydata/chap01/data1_1.csv')
head(data1_1,5)
性别 网购次数 满意度
1 女 6次以上 满意
2 男 3~5次 不满意
3 女 3~5次 不满意
4 男 3~5次 中立
5 女 1~2次 满意
# 查看数据结构
str(data1_1)
'data.frame': 2000 obs. of 3 variables:
$ 性别 : chr "女" "男" "女" "男" ...
$ 网购次数: chr "6次以上" "3~5次" "3~5次" "3~5次" ...
$ 满意度 : chr "满意" "不满意" "不满意" "中立" ...
# 生成满意度的一维表
mytable1 <- table(data1_1$满意度)
mytable1
不满意 满意 中立
800 520 680
# 将mytable1转换为百分比表
prop.table(mytable1) * 100
不满意 满意 中立
40 26 34
(二)二维列联表
二维列联表:一个名称放在“行”位置,另一个变量各类别放在“列”位置
# 生成性别和满意度的二维列联表
mytable2 <- table(data1_1$性别, data1_1$满意度)
mytable2
不满意 满意 中立
男 360 160 320
女 440 360 360
prop.table(mytable2) # 所占总量的百分比
不满意 满意 中立
男 0.18 0.08 0.16
女 0.22 0.18 0.18
prop.table(mytable2, 1) # 行汇总的百分比
不满意 满意 中立
男 0.4285714 0.1904762 0.3809524
女 0.3793103 0.3103448 0.3103448
prop.table(mytable2, 2) # 列汇总的百分比
不满意 满意 中立
男 0.4500000 0.3076923 0.4705882
女 0.5500000 0.6923077 0.5294118
addmargins(mytable2) # 为列联表添加边际和
不满意 满意 中立 Sum
男 360 160 320 840
女 440 360 360 1160
Sum 800 520 680 2000
(三)多维列联表
多维列联表:将一个或多个变量按“列”摆放,其余变按“行”摆放。
# 生成三维列联表(列变量为“满意度”)
mytable3 <- ftable(data1_1, row.vars = c("性别", "网购次数"), col.vars = "满意度")
mytable3
满意度 不满意 满意 中立
性别 网购次数
男 1~2次 117 57 106
3~5次 137 54 131
6次以上 106 49 83
女 1~2次 122 114 102
3~5次 179 141 162
6次以上 139 105 96
# 生成三维列联表(列变量为"性别"和"满意度")
mytable4 <- ftable(data1_1, row.vars = '网购次数', col.vars = c('性别', '满意度'))
mytable4
性别 男 女
满意度 不满意 满意 中立 不满意 满意 中立
网购次数
1~2次 117 57 106 122 114 102
3~5次 137 54 131 179 141 162
6次以上 106 49 83 139 105 96
# 使用structable函数生成多维表
library(vcd)
structable(data1_1)
网购次数 1~2次 3~5次 6次以上
性别 满意度
男 不满意 117 137 106
满意 57 54 49
中立 106 131 83
女 不满意 122 179 139
满意 114 141 105
中立 102 162 96
structable(网购次数 ~性别 + 满意度, data1_1)
网购次数 1~2次 3~5次 6次以上
性别 满意度
男 不满意 117 137 106
满意 57 54 49
中立 106 131 83
女 不满意 122 179 139
满意 114 141 105
中立 102 162 96
2、数值数据类别化
# 读入数据【某购物网站60天的销售额】
data1_2 <- read.csv('./mydata/chap01/data1_2.csv')
# 查看数据前5行
head(data1_2, 5)
销售额
1 572
2 588
3 678
4 604
5 606
# 查看数据结构
str(data1_2)
'data.frame': 60 obs. of 1 variable:
$ 销售额: int 572 588 678 604 606 686 623 537 566 578 ...
# 查看销售额字段值类型
class(data1_2$销售额)
[1] "integer"
(1)按组数分割
注:生成数值数据频数分布表,先将其类别化(转化为类别或因子数据)
nclass.Sturges(data1_2$销售额) #nclass.Sturges可算出大概数,具体组数可根据需要调整
v <- as.vector(data1_2$销售额) # 将销售额转化为向量
cut(v, breaks = 7) # 按组数切割:将数值向量切割成7组
[1] (561,590] (561,590] (649,679] (590,620] (590,620] (679,708] (620,649] (531,561] (561,590] (561,590] (649,679]
[12] (590,620] (620,649] (590,620] (561,590] (679,708] (620,649] (502,531] (620,649] (561,590] (531,561] (561,590]
[23] (531,561] (561,590] (561,590] (502,531] (620,649] (590,620] (531,561] (649,679] (620,649] (561,590] (620,649]
[34] (620,649] (620,649] (620,649] (620,649] (590,620] (561,590] (561,590] (561,590] (561,590] (531,561] (679,708]
[45] (649,679] (531,561] (561,590] (561,590] (620,649] (590,620] (590,620] (590,620] (590,620] (649,679] (561,590]
[56] (649,679] (502,531] (620,649] (590,620] (590,620]
Levels: (502,531] (531,561] (561,590] (590,620] (620,649] (649,679] (679,708]
cut(v, breaks = 7, right = F) # 左闭右开
[1] [561,590) [561,590) [649,679) [590,620) [590,620) [679,708) [620,649) [531,561) [561,590) [561,590) [649,679)
[12] [590,620) [620,649) [590,620) [561,590) [679,708) [620,649) [502,531) [620,649) [561,590) [531,561) [561,590)
[23] [531,561) [561,590) [561,590) [502,531) [620,649) [590,620) [531,561) [649,679) [620,649) [561,590) [620,649)
[34] [620,649) [620,649) [620,649) [620,649) [590,620) [561,590) [561,590) [561,590) [561,590) [531,561) [679,708)
[45] [649,679) [531,561) [561,590) [561,590) [620,649) [590,620) [590,620) [590,620) [590,620) [649,679) [561,590)
[56] [649,679) [502,531) [620,649) [590,620) [590,620)
Levels: [502,531) [531,561) [561,590) [590,620) [620,649) [649,679) [679,708)
data1_2$销售额类别 = cut(v, breaks = 5)
head(data1_2,5)
销售额 销售额类别
1 572 (543,584]
2 588 (584,626]
3 678 (667,708]
4 604 (584,626]
5 606 (584,626]
(2)按组距分割
# 组距=(最大值 - 最小值)/组数
(max(v) - min(v))/5
mi <- floor(min(v) / 41)
ma <- ceiling(max(v) / 41)
cut(v, breaks = 41*(mi:ma)) # 按组距切割:将数值向量切割成组距为41
[1] (533,574] (574,615] (656,697] (574,615] (574,615] (656,697] (615,656] (533,574] (533,574] (574,615] (656,697]
[12] (615,656] (615,656] (574,615] (533,574] (656,697] (615,656] (492,533] (615,656] (574,615] (533,574] (574,615]
[23] (533,574] (533,574] (533,574] (492,533] (615,656] (574,615] (533,574] (656,697] (615,656] (574,615] (615,656]
[34] (615,656] (615,656] (615,656] (615,656] (574,615] (574,615] (574,615] (533,574] (574,615] (533,574] (697,738]
[45] (656,697] (533,574] (574,615] (574,615] (615,656] (574,615] (574,615] (574,615] (574,615] (656,697] (574,615]
[56] (656,697] (492,533] (615,656] (574,615] (574,615]
Levels: (492,533] (533,574] (574,615] (615,656] (656,697] (697,738]
# 确定组数的常用方法
nclass.Sturges(v)
# 确定组距的方法:组距 = (最大值 - 最小值) / 组数
(max(v) - min(v)) / nclass.Sturges(v)
注:组数和组距可根据分析需要调整
# 分成间隔为30的组,右开
d <- table(cut(v, breaks = 30*(16:24), right = F))
dd <- data.frame(d) # 组织成数据框
dd
Var1 Freq
1 [480,510) 1
2 [510,540) 4
3 [540,570) 8
4 [570,600) 17
5 [600,630) 14
6 [630,660) 7
7 [660,690) 8
8 [690,720) 1
# 计算频数百分比,结果 保留2位小数
percent <- round(dd$Freq/sum(dd$Freq) * 100, 2)
df <- data.frame(dd, percent) # 组织成数据框
df
Var1 Freq percent
1 [480,510) 1 1.67
2 [510,540) 4 6.67
3 [540,570) 8 13.33
4 [570,600) 17 28.33
5 [600,630) 14 23.33
6 [630,660) 7 11.67
7 [660,690) 8 13.33
8 [690,720) 1 1.67
# 重新命名并组织成频数分布表
mytable <- data.frame(分组 = df$Var1, 频数 = df$Freq, 频数百分比 = df$percent)
mytable
分组 频数 频数百分比
1 [480,510) 1 1.67
2 [510,540) 4 6.67
3 [540,570) 8 13.33
4 [570,600) 17 28.33
5 [600,630) 14 23.33
6 [630,660) 7 11.67
7 [660,690) 8 13.33
8 [690,720) 1 1.67
# 实际分组时,可将组距确定易于理解的值,如50
# 分组间隔为50,并生成频数分布表
d <- table(cut(v, breaks = c(500, 550, 600, 650, 700, 750), right = F))
d
[500,550) [550,600) [600,650) [650,700) [700,750)
9 21 21 8 1
(3)使用DescTools包中的Freq函数生成频数分布表
data1_2 <- read.csv('./mydata/chap01/data1_2.csv')
# install.packages('DescTools')
library(DescTools)
# A.默认分组,含上限值
# 简单代码得到组别(level)、各组的频数(freq)、各组频数百分比(perc)、累积频数(cumfreq)、累积频数百分比(cumprec
tab <- Freq(data1_2$销售额)
tab
level freq perc cumfreq cumperc
1 [500,550] 9 15.0% 9 15.0%
2 (550,600] 21 35.0% 30 50.0%
3 (600,650] 21 35.0% 51 85.0%
4 (650,700] 8 13.3% 59 98.3%
5 (700,750] 1 1.7% 60 100.0%
# B.使用Freq函数生成频数分布表,指定组距=20
20*(25:36)
tab1 <- Freq(data1_2$销售额, breaks = 20*(25:36), right = F)
tab1
tab2 <- data.frame(分组 = tab1$level,
频数 = tab1$freq,
频数百分比 = tab1$perc * 100,
累积频数 = tab1$cumfreq,
累积百分比 = tab1$cumperc * 100)
print(tab2, digits = 3) # 用print函数定义输出结果的小数位数
分组 频数 频数百分比 累积频数 累积百分比
1 [500,520) 2 3.33 2 3.33
2 [520,540) 3 5.00 5 8.33
3 [540,560) 4 6.67 9 15.00
4 [560,580) 9 15.00 18 30.00
5 [580,600) 12 20.00 30 50.00
6 [600,620) 8 13.33 38 63.33
7 [620,640) 9 15.00 47 78.33
8 [640,660) 4 6.67 51 85.00
9 [660,680) 6 10.00 57 95.00
10 [680,700) 2 3.33 59 98.33
11 [700,720] 1 1.67 60 100.00
四、数据类型的转换
1、将变量转换为向量
table1_1 <- read.csv('./mydata/chap01/table1_1.csv')
table1_1
姓名 统计学 数学 经济学
1 刘文涛 68 85 84
2 王宇翔 85 91 63
3 田思雨 74 74 61
4 徐丽娜 88 100 49
5 丁文彬 63 82 89
vector1 <- as.vector(table1_1$统计学) # 将统计学分数转换成向量
# 将统计学和数学分数合并转换成一个向量
vector2 <- as.vector(c(table1_1$统计学, table1_1$数学))
vector1;vector2
[1] 68 85 74 88 63
[1] 68 85 74 88 63 85 91 74 100 82
2、将数据框转换成矩阵
# 将table1_1中的第2~4列转换成矩阵mat
mat <- as.matrix(table1_1[, 2:4])
mat
# 矩阵的行名为table1_1第1列的名称
rownames(mat) = table1_1[, 1]
mat
统计学 数学 经济学
刘文涛 68 85 84
王宇翔 85 91 63
田思雨 74 74 61
徐丽娜 88 100 49
丁文彬 63 82 89
# 将矩阵转换成数据框
as.data.frame(mat)
3、将列联表转化成数据框
library(DescTools)
# 将列联表转化成数据框
df <- Untable(mytable3)
head(df, 3) #后三行tail(df, 3)
性别 网购次数 满意度
1 男 1~2次 不满意
2 男 1~2次 不满意
3 男 1~2次 不满意
# 将列联表转化成带有类别频数的数据框
data1_1 <- read.csv('./mydata/chap01/data1_1.csv')
tab <- ftable(data1_1) # 生成列联表(也可以使用table函数生成列联表)
df <- as.data.frame(tab) # 将列联表转化成带有类别频数的数据框
head(df)
性别 网购次数 满意度 Freq
1 男 1~2次 不满意 117
2 女 1~2次 不满意 122
3 男 3~5次 不满意 137
4 女 3~5次 不满意 179
5 男 6次以上 不满意 106
6 女 6次以上 不满意 139
reshape2::melt(table(data1_1)) # 与ftable(data1_1)效果相同
性别 网购次数 满意度 value
1 男 1~2次 不满意 117
2 女 1~2次 不满意 122
3 男 3~5次 不满意 137
4 女 3~5次 不满意 179
5 男 6次以上 不满意 106
6 女 6次以上 不满意 139
7 男 1~2次 满意 57
8 女 1~2次 满意 114
9 男 3~5次 满意 54
10 女 3~5次 满意 141
11 男 6次以上 满意 49
12 女 6次以上 满意 105
13 男 1~2次 中立 106
14 女 1~2次 中立 102
15 男 3~5次 中立 131
16 女 3~5次 中立 162
17 男 6次以上 中立 83
18 女 6次以上 中立 96
4、将短格式数据转化成长格式数据
(1)将短格式数据转化成长格式数据(数据框中有标识变量(类别因子))
table1_1
姓名 统计学 数学 经济学
1 刘文涛 68 85 84
2 王宇翔 85 91 63
3 田思雨 74 74 61
4 徐丽娜 88 100 49
5 丁文彬 63 82 89
library(reshape2)
melt(table1_1, id.vars = '姓名') # 保持'姓名'列固定,其它列会自动融合
# variable.name、value.name分别用来设定列变量和值的名称
tab_long <- melt(table1_1, id.vars = '姓名', variable.name = '课程', value.name = '分数')
tab_long
姓名 课程 分数
1 刘文涛 统计学 68
2 王宇翔 统计学 85
3 田思雨 统计学 74
4 徐丽娜 统计学 88
5 丁文彬 统计学 63
6 刘文涛 数学 85
7 王宇翔 数学 91
8 田思雨 数学 74
9 徐丽娜 数学 100
10 丁文彬 数学 82
11 刘文涛 经济学 84
12 王宇翔 经济学 63
13 田思雨 经济学 61
14 徐丽娜 经济学 49
15 丁文彬 经济学 89
(2)将短格式数据转化成长格式数据(数据框中无标识变量)
table1_4 <- read.csv('./mydata/chap01/table1_4.csv')
table1_4
统计学 数学 经济学
1 68 85 84
2 85 91 63
3 74 74 61
4 88 100 49
5 63 82 89
tab_long <- melt(table1_4, variable.name = '课程', value.name = '分数') # 不使用标识变量直接融合
tab_long
课程 分数
1 统计学 68
2 统计学 85
3 统计学 74
4 统计学 88
5 统计学 63
6 数学 85
7 数学 91
8 数学 74
9 数学 100
10 数学 82
11 经济学 84
12 经济学 63
13 经济学 61
14 经济学 49
15 经济学 89
使用tidyr包中的gather函数融合数据
library(tidyr)
# key、value分别用来设定列变量和值的名称
df1 <- gather(table1_1, key = '课程', value = '分数', '统计学', '数学', '经济学')
df1