R-切割数据
1.cut
cut()
函数用于将连续型数据离散为离散的区间(分组),常用于将数值变量转换为分类变量(如将年龄分为 “儿童”“青年”“中年”“老年”)。
cut(x, breaks, labels = NULL, include.lowest = FALSE, right = TRUE, ...)
参数说明
x
:需要分箱的连续型向量(数值向量)。breaks
:指定分组的分割点,可以是:- 整数:表示将
x
等分为breaks
个区间; - 数值向量:直接指定分割点(如
c(0, 10, 20, 30)
表示按 0、10、20、30 分割)。
- 整数:表示将
labels
:为每个区间指定标签(字符向量),长度需与区间数量一致。include.lowest
:逻辑值(默认FALSE
),若为TRUE
,则包含区间的最小值(避免最小值被遗漏)。right
:逻辑值(默认TRUE
),若为TRUE
,区间为右闭左开(如(10, 20]
);若为FALSE
,则为左闭右开(如[10, 20)
)。
1.2.示例
scores <- c(85, 92, 78, 65, 58, 90, 88, 76)
score_groups <- cut(x = scores,breaks = c(0, 60, 80, 100), # 分割点:0-60、60-80、80-100labels = c("不及格", "良好", "优秀"), # 区间标签include.lowest = TRUE # 包含最小值(0),确保 60 分被划入"良好"
)
print(score_groups)
#[1] 优秀 优秀 良好 良好 不及格 优秀 优秀 良好
#Levels: 不及格 良好 优秀
#结果是一个因子#等距分箱
ages <- c(22, 18, 35, 42, 58, 29, 65, 48)
age_groups <- cut(ages, breaks = 3)
print(age_groups)
#[1] (18,33.7] (18,33.7] (33.7,49.3] (33.7,49.3] (49.3,65] (18,33.7] (49.3,65] (33.7,49.3]
#Levels: (18,33.7] (33.7,49.3] (49.3,65]#right参数
x <- c(10,20,30)
cut(x,breaks = c(10,20,30),right = TRUE )
cut(x,breaks = c(10,20,30),right = FALSE)
#[1] <NA> (10,20] (20,30]
#Levels: (10,20] (20,30]
#[1] [10,20) [20,30) <NA>
#Levels: [10,20) [20,30)
1.3.应用场景
数据离散化:将连续变量(如收入、成绩)转换为分类变量,便于分组分析。
创建分组标签:为可视化(如直方图、箱线图)或建模(如逻辑回归)提供分类依据。
分位数分组:结合 quantile()
按分位数分割(如四分位数、五分位数):
1.4.注意事项
缺失值处理:不在 breaks
范围内的值会被标记为 NA
(缺失),需通过 include.lowest
等参数避免。
因子输出:cut()
返回的是因子类型,若需字符型,可加 as.character()
转换。
分割点顺序:breaks
必须是递增的数值向量,否则会报错。
2.Hmisc::cut2
2.1语法
cut2(x, cuts, m, g, levels.mean = FALSE, digits, ...)
主要参数说明:
x
:需要分箱的连续型向量(数值向量)。cuts
:自定义分割点(类似基础cut()
的breaks
),如c(0, 50, 100)
。m
:每个区间至少包含的观测值数量(优先级高于g
)。g
:指定分组数量(等频分组,即按分位数大致均分数据)。levels.mean
:逻辑值(默认FALSE
),若为TRUE
,则用区间均值作为标签,而非区间范围。digits
:区间标签的小数位数(控制显示精度)。
2.2与cut区别
等频分组更便捷:通过 g
参数直接指定分组数,自动按分位数划分(每组数量大致相等)。
控制最小样本量:m
参数确保每个区间至少有 m
个观测值,避免区间包含样本太少。
标签更友好:默认标签格式更简洁,且支持用均值作为标签。
2.3示例
2.3.1等频分组,g参数
library(Hmisc)set.seed(123)
x <- rnorm(100, mean = 50, sd = 10)
print(x)
# 等频分组
groups <- Hmisc::cut2(x, g = 4)
print(groups)
# 查看分组结果及每组数量
table(groups)> print(groups)[1] [26.9,45.1) [45.1,50.7) [57.0,71.9] [50.7,57.0) [50.7,57.0) [57.0,71.9] [50.7,57.0) [26.9,45.1) [26.9,45.1)[10] [45.1,50.7) [57.0,71.9] [50.7,57.0) [50.7,57.0) [50.7,57.0) [26.9,45.1) [57.0,71.9] [50.7,57.0) [26.9,45.1)[19] [57.0,71.9] [45.1,50.7) [26.9,45.1) [45.1,50.7) [26.9,45.1) [26.9,45.1) [26.9,45.1) [26.9,45.1) [57.0,71.9][28] [50.7,57.0) [26.9,45.1) [57.0,71.9] [50.7,57.0) [45.1,50.7) [57.0,71.9] [57.0,71.9] [57.0,71.9] [50.7,57.0)[37] [50.7,57.0) [45.1,50.7) [45.1,50.7) [45.1,50.7) [26.9,45.1) [45.1,50.7) [26.9,45.1) [57.0,71.9] [57.0,71.9][46] [26.9,45.1) [45.1,50.7) [45.1,50.7) [57.0,71.9] [45.1,50.7) [50.7,57.0) [45.1,50.7) [45.1,50.7) [57.0,71.9][55] [45.1,50.7) [57.0,71.9] [26.9,45.1) [50.7,57.0) [50.7,57.0) [50.7,57.0) [50.7,57.0) [26.9,45.1) [45.1,50.7)[64] [26.9,45.1) [26.9,45.1) [50.7,57.0) [50.7,57.0) [45.1,50.7) [57.0,71.9] [57.0,71.9] [45.1,50.7) [26.9,45.1)[73] [57.0,71.9] [26.9,45.1) [26.9,45.1) [57.0,71.9] [45.1,50.7) [26.9,45.1) [50.7,57.0) [45.1,50.7) [45.1,50.7)[82] [50.7,57.0) [45.1,50.7) [50.7,57.0) [45.1,50.7) [50.7,57.0) [57.0,71.9] [50.7,57.0) [45.1,50.7) [57.0,71.9][91] [57.0,71.9] [50.7,57.0) [50.7,57.0) [26.9,45.1) [57.0,71.9] [26.9,45.1) [57.0,71.9] [57.0,71.9] [45.1,50.7)
[100] [26.9,45.1)
Levels: [26.9,45.1) [45.1,50.7) [50.7,57.0) [57.0,71.9]> table(groups)
groups
[26.9,45.1) [45.1,50.7) [50.7,57.0) [57.0,71.9] 25 25 25 25
2.3.2控制每组最小样本量,m参数
# 确保每个区间至少有10个观测值
groups_m <- cut2(x, m = 10)
table(groups_m)
> table(groups_m)
groups_m
[26.9,39.3) [39.3,43.7) [43.7,46.2) [46.2,47.8) [47.8,50.7) [50.7,53.3) [53.3,55.5) [55.5,59.0) [59.0,63.6) [63.6,71.9] 10 10 10 10 10 10 10 10 10 10
2.3.3自定义分割点,cuts参数
# 按自定义分割点分箱
groups_cuts <- cut2(x, cuts = c(40, 50, 60))
table(groups_cuts)
groups_cuts
[26.9,40.0) [40.0,50.0) [50.0,60.0) [60.0,71.9] 14 34 35 17
2.3.4用区间均值作为标签,levels.mean = TRUE
# 分组后用均值作为标签(而非区间范围)
groups_mean <- cut2(x, g = 4, levels.mean = TRUE, digits = 1)
table(groups_mean)
> table(groups_mean)
groups_mean
40 48 54 63
25 25 25 25
2.3.总结
等频分组更智能:g
参数自动按分位数划分,避免基础 cut()
按等距划分可能导致的组内样本量不均。
灵活控制分组粒度:m
参数确保每组有足够样本,适合小样本数据。
标签更实用:支持均值标签,便于后续分析和可视化。
3.重塑数据
“熔化(melt)” 和 “铸造(cast)” 是重塑数据的两种核心操作,主要用于将数据在宽格式(wide format) 和长格式(long format) 之间转换。这两种操作在 reshape2
或 reshape
包中实现,是数据处理和可视化(如 ggplot2)的重要基础。
3.1基本概念:宽格式和长格式
宽格式:每行代表一个观测单元,每列代表一个变量,(同一属性的不同类别分散在多列中),属性类别通常直接对应列名。宽格式中每一列代表同一属性的不同类别,或者不同属性的度量值。
如:
ID 2020 2021 2022
A 100 150 200
B 120 180 220
2020,2021,2022都是年份这个属性的不同类别,而每行A和B是观测的对象(可以看成另一个属性),然后每个值,就是该对象对应某年的度量值。
长格式:每行代表一个观测单元的某个属性值,用额外的列标记属性类别(同一属性的不同类别集中在一列中)。
ID year sales
A 2020 100
A 2021 150
A 2022 200
B 2020 120
B 2021 180
B 2022 220
3.1.1总结
宽格式:属性的不同类别以列名形式存在,每列对应一个具体类别;
长格式:属性的所有类别集中在同一列中,用该列的值来区分不同类别。
3.2熔化(melt)从宽格式->长格式
“熔化” 是将宽格式数据转换为长格式,保留标识变量(id variables),将其他变量 “堆叠” 为 “属性 - 值” 对(即新增 “变量名” 和 “变量值” 两列)。
3.2.1语法reshape2::melt()
melt(data, id.vars, measure.vars, variable.name = "variable", value.name = "value")
data
:要转换的数据框。id.vars
:标识变量(保持不变的列,如示例中的ID
)。measure.vars
:要被 “熔化” 的变量(需要堆叠的列,如示例中的2020
/2021
/2022
)。variable.name
:新增的 “属性类别” 列的名称(默认variable
)。value.name
:新增的 “属性值” 列的名称(默认value
)。
3.2.2示例
library(reshape2)
head(mtcars,2)
mtcars$carName <- rownames(mtcars)
head(mtcars)
carMelt <- melt(mtcars,id.vars = c('carName','gear','cyl'),measure.vars = c('mpg','hp'))
head(carMelt,3)
print(carMelt)> head(mtcars)mpg cyl disp hp drat wt qsec vs am gear carb carName
Mazda RX4 21.0 6 160 110 3.90 2.620 16.46 0 1 4 4 Mazda RX4
Mazda RX4 Wag 21.0 6 160 110 3.90 2.875 17.02 0 1 4 4 Mazda RX4 Wag
Datsun 710 22.8 4 108 93 3.85 2.320 18.61 1 1 4 1 Datsun 710
Hornet 4 Drive 21.4 6 258 110 3.08 3.215 19.44 1 0 3 1 Hornet 4 Drive
Hornet Sportabout 18.7 8 360 175 3.15 3.440 17.02 0 0 3 2 Hornet Sportabout
Valiant 18.1 6 225 105 2.76 3.460 20.22 1 0 3 1 Valiant> head(carMelt,3)carName gear cyl variable value
1 Mazda RX4 4 6 mpg 21.0
2 Mazda RX4 Wag 4 6 mpg 21.0
3 Datsun 710 4 4 mpg 22.8
> print(carMelt)carName gear cyl variable value
1 Mazda RX4 4 6 mpg 21.0
2 Mazda RX4 Wag 4 6 mpg 21.0
3 Datsun 710 4 4 mpg 22.8
4 Hornet 4 Drive 3 6 mpg 21.4
5 Hornet Sportabout 3 8 mpg 18.7
6 Valiant 3 6 mpg 18.1
7 Duster 360 3 8 mpg 14.3
8 Merc 240D 4 4 mpg 24.4
9 Merc 230 4 4 mpg 22.8
10 Merc 280 4 6 mpg 19.2
11 Merc 280C 4 6 mpg 17.8
12 Merc 450SE 3 8 mpg 16.4
13 Merc 450SL 3 8 mpg 17.3
14 Merc 450SLC 3 8 mpg 15.2
15 Cadillac Fleetwood 3 8 mpg 10.4
16 Lincoln Continental 3 8 mpg 10.4
17 Chrysler Imperial 3 8 mpg 14.7
18 Fiat 128 4 4 mpg 32.4
19 Honda Civic 4 4 mpg 30.4
20 Toyota Corolla 4 4 mpg 33.9
21 Toyota Corona 3 4 mpg 21.5
22 Dodge Challenger 3 8 mpg 15.5
23 AMC Javelin 3 8 mpg 15.2
24 Camaro Z28 3 8 mpg 13.3
25 Pontiac Firebird 3 8 mpg 19.2
26 Fiat X1-9 4 4 mpg 27.3
27 Porsche 914-2 5 4 mpg 26.0
28 Lotus Europa 5 4 mpg 30.4
29 Ford Pantera L 5 8 mpg 15.8
30 Ferrari Dino 5 6 mpg 19.7
31 Maserati Bora 5 8 mpg 15.0
32 Volvo 142E 4 4 mpg 21.4
33 Mazda RX4 4 6 hp 110.0
34 Mazda RX4 Wag 4 6 hp 110.0
35 Datsun 710 4 4 hp 93.0
36 Hornet 4 Drive 3 6 hp 110.0
37 Hornet Sportabout 3 8 hp 175.0
38 Valiant 3 6 hp 105.0
39 Duster 360 3 8 hp 245.0
40 Merc 240D 4 4 hp 62.0
41 Merc 230 4 4 hp 95.0
42 Merc 280 4 6 hp 123.0
43 Merc 280C 4 6 hp 123.0
44 Merc 450SE 3 8 hp 180.0
45 Merc 450SL 3 8 hp 180.0
46 Merc 450SLC 3 8 hp 180.0
47 Cadillac Fleetwood 3 8 hp 205.0
48 Lincoln Continental 3 8 hp 215.0
49 Chrysler Imperial 3 8 hp 230.0
50 Fiat 128 4 4 hp 66.0
51 Honda Civic 4 4 hp 52.0
52 Toyota Corolla 4 4 hp 65.0
53 Toyota Corona 3 4 hp 97.0
54 Dodge Challenger 3 8 hp 150.0
55 AMC Javelin 3 8 hp 150.0
56 Camaro Z28 3 8 hp 245.0
57 Pontiac Firebird 3 8 hp 175.0
58 Fiat X1-9 4 4 hp 66.0
59 Porsche 914-2 5 4 hp 91.0
60 Lotus Europa 5 4 hp 113.0
61 Ford Pantera L 5 8 hp 264.0
62 Ferrari Dino 5 6 hp 175.0
63 Maserati Bora 5 8 hp 335.0
64 Volvo 142E 4 4 hp 109.0
3.3铸造:从长格式->宽格式
“铸造” 是熔化的逆操作,将长格式数据转换回宽格式,通过指定 “行标识”“列标识” 和 “值” 来重塑数据。
3.3.1. reshape2::dcast()
语法(用于数据框)
dcast(data, formula, fun.aggregate = NULL, value.var)
data
:长格式数据框。formula
:格式为行标识 ~ 列标识
(用~
分隔,左侧是行分组,右侧是列分组)。fun.aggregate
:聚合函数(当存在多值对应同一位置时,如sum
/mean
,默认不聚合)。value.var
:指定用于填充单元格的值所在的列(即长格式中的 “值列”)。
3.3.2示例
# 铸造
wide_data2 <- dcast(carMelt,cyl~variable,value.var = "value")
print(wide_data2)Aggregation function missing: defaulting to length
> print(wide_data2)cyl mpg hp
1 4 11 11
2 6 7 7
3 8 14 14
报错:Aggregation function missing: defaulting to length
同一行和列的交叉位置存在多个值,但未指定如何聚合这些值,此时函数默认使用 length()
函数(统计值的数量)作为聚合方式。
wide_data2 <- dcast(carMelt,cyl~variable,fun.aggregate = mean,value.var = "value")
print(wide_data2)
> print(wide_data2)cyl mpg hp
1 4 26.66364 82.63636
2 6 19.74286 122.28571
3 8 15.10000 209.21429
3.3.3 reshape2::acast()
基本语法
它的返回结果是数组(array) 或矩阵(matrix),而非数据框(data frame)。这使得它特别适合处理多维度(超过 2 维)的数据重塑,或需要矩阵 / 数组输出的场景。
acast(data, formula, fun.aggregate = NULL, value.var = "value", ...)
参数说明:
data
:长格式数据框(需要转换的数据)。formula
:重塑公式,格式为行 ~ 列 ~ 维度3 ~ ...
(用~
分隔不同维度,支持 1 维、2 维或更高维)。fun.aggregate
:聚合函数(当同一交叉位置有多个值时使用,如sum
、mean
;默认无,若有重复值会报错,需显式指定)。value.var
:指定用于填充数组 / 矩阵的值所在的列(长格式中的 “值列”,默认value
)。
3.3.4 acast示例
wide_data3 <- acast(carMelt,cyl~gear~variable,value.var = "value")
print(wide_data3)
wide_data3 <- acast(carMelt,cyl~gear~variable,value.var = "value",fun.aggregate = mean)
print(wide_data3)> print(wide_data3)
, , mpg3 4 5
4 1 8 2
6 2 4 1
8 12 0 2, , hp3 4 5
4 1 8 2
6 2 4 1
8 12 0 2> print(wide_data3)
, , mpg3 4 5
4 21.50 26.925 28.2
6 19.75 19.750 19.7
8 15.05 NaN 15.4, , hp3 4 5
4 97.0000 76.0 102.0
6 107.5000 116.5 175.0
8 194.1667 NaN 299.5
3.3.5区别
函数 | 返回类型 | 适用场景 | 公式维度限制 |
---|---|---|---|
dcast | 数据框(data frame) | 2 维数据重塑,需要保留行 / 列名称 | 最多 2 维(行~列) |
acast | 数组(array)/ 矩阵 | 1 维、2 维或更高维数据重塑,需矩阵 / 数组输出 | 支持任意维度(行~列~维度 3...) |