Chapter 3 数据转换
绘制图表很简单。然而,有时要将数据整理成生成图表所需的形式并不那么容易。
3.2 什么是tidy(整齐)的数据
下面是 Hadley Wickham 对整洁数据的定义:
数据集是杂乱的还是整洁的,取决于行、列和表如何与观察值、变量和类型进行匹配。整齐的数据:
- 每个变量形成一列。(Each variable forms a column.)
- 每个观察点组成一行。(Each observation forms a row.)
- 每个观测单位在表中形成一个值。(Each observational unit forms a value in the table.)
在本章节极少对数据进行转换的一些工具.
3.3 pivot_longer
将宽数据转换成为长数据, 首先查看原始数据
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr 1.1.4 ✔ readr 2.1.4
## ✔ forcats 1.0.0 ✔ stringr 1.5.1
## ✔ ggplot2 3.4.4 ✔ tibble 3.2.1
## ✔ lubridate 1.9.3 ✔ tidyr 1.3.0
## ✔ purrr 1.0.2
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag() masks stats::lag()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
## mpg cyl disp hp drat wt qsec vs am gear carb
## Mazda RX4 21.0 6 160 110 3.90 2.620 16.46 0 1 4 4
## Mazda RX4 Wag 21.0 6 160 110 3.90 2.875 17.02 0 1 4 4
## Datsun 710 22.8 4 108 93 3.85 2.320 18.61 1 1 4 1
## Hornet 4 Drive 21.4 6 258 110 3.08 3.215 19.44 1 0 3 1
## Hornet Sportabout 18.7 8 360 175 3.15 3.440 17.02 0 0 3 2
## Valiant 18.1 6 225 105 2.76 3.460 20.22 1 0 3 1
接下来使用pivot_longer 将数据集转换成为长数据:
mtcars1 <- mtcars %>%
rownames_to_column("carname") %>%
pivot_longer(cols = !carname, names_to = "Parameters",values_to = "value")
mtcars1 %>%
head()
## # A tibble: 6 × 3
## carname Parameters value
## <chr> <chr> <dbl>
## 1 Mazda RX4 mpg 21
## 2 Mazda RX4 cyl 6
## 3 Mazda RX4 disp 160
## 4 Mazda RX4 hp 110
## 5 Mazda RX4 drat 3.9
## 6 Mazda RX4 wt 2.62
3.4 pivot_wider
将长数据转化成为宽数据:
## # A tibble: 32 × 12
## carname mpg cyl disp hp drat wt qsec vs am gear carb
## <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 Mazda RX4 21 6 160 110 3.9 2.62 16.5 0 1 4 4
## 2 Mazda RX4 … 21 6 160 110 3.9 2.88 17.0 0 1 4 4
## 3 Datsun 710 22.8 4 108 93 3.85 2.32 18.6 1 1 4 1
## 4 Hornet 4 D… 21.4 6 258 110 3.08 3.22 19.4 1 0 3 1
## 5 Hornet Spo… 18.7 8 360 175 3.15 3.44 17.0 0 0 3 2
## 6 Valiant 18.1 6 225 105 2.76 3.46 20.2 1 0 3 1
## 7 Duster 360 14.3 8 360 245 3.21 3.57 15.8 0 0 3 4
## 8 Merc 240D 24.4 4 147. 62 3.69 3.19 20 1 0 4 2
## 9 Merc 230 22.8 4 141. 95 3.92 3.15 22.9 1 0 4 2
## 10 Merc 280 19.2 6 168. 123 3.92 3.44 18.3 1 0 4 4
## # ℹ 22 more rows
长数据与宽数据的转换是非常常用的操作.
3.5 常用数据处理函数
我们将使用来自 MASS 的biopsy数据集作为例子。
##
## Attaching package: 'MASS'
## The following object is masked from 'package:dplyr':
##
## select
## ID V1 V2 V3 V4 V5 V6 V7 V8 V9 class
## 1 1000025 5 1 1 1 2 1 3 1 1 benign
## 2 1002945 5 4 4 5 7 10 3 2 1 benign
## 3 1015425 3 1 1 1 2 2 3 1 1 benign
## 4 1016277 6 8 8 1 3 4 3 7 1 benign
## 5 1017023 4 1 1 3 2 1 3 1 1 benign
## 6 1017122 8 10 10 8 7 10 9 7 1 malignant
3.5.1 rename
在获取数据时,我们注意到列的名称非常模糊。我们希望更改列的名称,以便查看者能够了解它们所引用的值。我们使用重命名来修改列名。
biopsy_new <- rename(biopsy,
thickness = V1,cell_size = V2,
cell_shape = V3, marg_adhesion = V4,
epithelial_cell_size = V5, bare_nuclei = V6,
chromatin = V7, norm_nucleoli = V8, mitoses = V9)
head(biopsy_new)
## ID thickness cell_size cell_shape marg_adhesion epithelial_cell_size
## 1 1000025 5 1 1 1 2
## 2 1002945 5 4 4 5 7
## 3 1015425 3 1 1 1 2
## 4 1016277 6 8 8 1 3
## 5 1017023 4 1 1 3 2
## 6 1017122 8 10 10 8 7
## bare_nuclei chromatin norm_nucleoli mitoses class
## 1 1 3 1 1 benign
## 2 10 3 2 1 benign
## 3 2 3 1 1 benign
## 4 4 3 7 1 benign
## 5 1 3 1 1 benign
## 6 10 9 7 1 malignant
3.5.2 select
Select 是按列执行的操作。具体来说,只返回指定的列。
#selecting all except the columns chromatin and mitoses
biopsy_new <- biopsy_new %>% dplyr::select(-chromatin,-mitoses)
head(biopsy_new,5)
## ID thickness cell_size cell_shape marg_adhesion epithelial_cell_size
## 1 1000025 5 1 1 1 2
## 2 1002945 5 4 4 5 7
## 3 1015425 3 1 1 1 2
## 4 1016277 6 8 8 1 3
## 5 1017023 4 1 1 3 2
## bare_nuclei norm_nucleoli class
## 1 1 1 benign
## 2 10 2 benign
## 3 2 1 benign
## 4 4 7 benign
## 5 1 1 benign
3.5.3 mutate
Mutate 函数从已存在的变量中计算新变量,并将它们添加到数据集中。它提供数据已经包含但从未显示的信息。
#normalize the bare nuclei values
maximum_bare_nuclei<-max(biopsy_new$bare_nuclei,na.rm=TRUE)
biopsy_new <- biopsy_new %>% mutate(bare_nuclei=bare_nuclei/maximum_bare_nuclei)
head(biopsy_new,5)
## ID thickness cell_size cell_shape marg_adhesion epithelial_cell_size
## 1 1000025 5 1 1 1 2
## 2 1002945 5 4 4 5 7
## 3 1015425 3 1 1 1 2
## 4 1016277 6 8 8 1 3
## 5 1017023 4 1 1 3 2
## bare_nuclei norm_nucleoli class
## 1 0.1 1 benign
## 2 1.0 2 benign
## 3 0.2 1 benign
## 4 0.4 7 benign
## 5 0.1 1 benign
3.5.4 filter
Filter 是行操作。它返回只包含某些行的修改后的副本。此函数根据其参数中提供的条件筛选行
## ID thickness cell_size cell_shape marg_adhesion epithelial_cell_size
## 1 1016277 6 8 8 1 3
## 2 1017122 8 10 10 8 7
## 3 1044572 8 7 5 10 7
## 4 1047630 7 4 6 4 6
## 5 1050670 10 7 7 6 4
## bare_nuclei norm_nucleoli class
## 1 0.4 7 benign
## 2 1.0 7 malignant
## 3 0.9 5 malignant
## 4 0.1 3 malignant
## 5 1.0 1 malignant
3.5.5 arrange
对数据进行排序
## ID thickness cell_size cell_shape marg_adhesion epithelial_cell_size
## 1 1050718 6 1 1 1 2
## 2 1204898 6 1 1 1 2
## 3 1223967 6 1 3 1 2
## 4 543558 6 1 3 1 4
## 5 63375 9 1 2 6 4
## 6 752904 10 1 1 1 2
## bare_nuclei norm_nucleoli class
## 1 0.1 1 benign
## 2 0.1 1 benign
## 3 0.1 1 benign
## 4 0.5 10 malignant
## 5 1.0 7 malignant
## 6 1.0 4 malignant
3.5.6 group_by and summarize
总结函数使用数据创建一个新的数据框架,其中包含最小值、最大值、平均值等总结统计信息。这些统计函数必须是以值的向量作为输入并输出单个值的聚合函数。
biopsy_grouped <- group_by(biopsy_new,class)
summarize(biopsy_grouped, max(thickness), mean(cell_size), var(norm_nucleoli))
## # A tibble: 2 × 4
## class `max(thickness)` `mean(cell_size)` `var(norm_nucleoli)`
## <fct> <int> <dbl> <dbl>
## 1 benign 8 2.67 5.93
## 2 malignant 10 6.73 11.3
3.5.7 slice_max (slice_min)
Slice _ max 函数可以帮助您查找特定列的前 n 个值。
## ID thickness cell_size cell_shape marg_adhesion epithelial_cell_size
## 1 1050670 10 7 7 6 4
## 2 1054593 10 5 5 3 6
## 3 1072179 10 7 7 3 8
## 4 1080185 10 10 10 8 6
## 5 1099510 10 4 3 1 3
## 6 1103608 10 10 10 4 8
## bare_nuclei norm_nucleoli class
## 1 1.0 1 malignant
## 2 0.7 10 malignant
## 3 0.5 4 malignant
## 4 0.1 9 malignant
## 5 0.3 5 malignant
## 6 0.1 10 malignant
3.6 Data Cleaning
3.6.2 Replace Values
接下来我们将讨论如何替换数据集中的特定值
students <- c("John", "Jane", "Joe", "Janet")
grades <- c(83, 97, 74, 27)
df <- data.frame(student = students, grade = grades)
我们需要用60代替任何低于60的等级
3.6.3 Drop Columns
接下来,我们可以通过指定要保留的列或指定要删除的列来删除列
## mpg cyl disp hp drat wt qsec vs am gear carb
## Mazda RX4 21.0 6 160 110 3.90 2.620 16.46 0 1 4 4
## Mazda RX4 Wag 21.0 6 160 110 3.90 2.875 17.02 0 1 4 4
## Datsun 710 22.8 4 108 93 3.85 2.320 18.61 1 1 4 1
## Hornet 4 Drive 21.4 6 258 110 3.08 3.215 19.44 1 0 3 1
## Hornet Sportabout 18.7 8 360 175 3.15 3.440 17.02 0 0 3 2
## Valiant 18.1 6 225 105 2.76 3.460 20.22 1 0 3 1
也可以是用:
如果希望使用索引号而不是列名,可以删除列的另一种方法如下所示