forked from perlatex/R_for_Data_Science
-
Notifications
You must be signed in to change notification settings - Fork 0
/
tibble.Rmd
478 lines (289 loc) · 8.4 KB
/
tibble.Rmd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
# 简单数据框 {#tibble}
```{r tibble-1, message = FALSE, warning = FALSE}
library(tidyverse)
library(tibble) # 事实上,library(tidyverse)已经加装了library(tibble)
```
## tidyverse 家族
前面陆续介绍了tidyverse家族,家庭主要成员包括
| 功能 | 宏包 |
|:-----|:------------|
有颜值担当 | ggplot2 |
数据处理王者 | dplyr |
数据转换专家 | tidyr |
数据载入利器 | readr |
循环加速器 | purrr |
强化数据框 | tibble |
字符串处理 | stringr |
因子处理 | forcats |
## 人性化的tibble
- tibble是用来替换data.frame类型的扩展的数据框
- tibble继承了data.frame,是弱类型的。换句话说,tibble是data.frame的子类型
- tibble与data.frame有相同的语法,使用起来更方便
- tibble更早的检查数据,方便写出更干净、更多富有表现力的代码
tibble对data.frame做了重新的设定:
* tibble,不关心输入类型,可存储任意类型,包括list类型
* tibble,没有行名设置 row.names
* tibble,支持任意的列名
* tibble,会自动添加列名
* tibble,类型只能回收长度为1的输入
* tibble,会懒加载参数,并按顺序运行
* tibble,是tbl_df类型
## tibble 与 data.frame
传统创建数据框
```{r tibble-2}
data.frame(
a = 1:5,
b = letters[1:5]
)
```
发现,`data.frame()`会自动将**字符串型**的变量转换成**因子型**,如果想保持原来的字符串型,就得
```{r tibble-3}
data.frame(
a = 1:5,
b = letters[1:5],
stringsAsFactors = FALSE
)
```
```{block tibble-4, type="danger"}
Note:
- 在R 4.0 后,`data.frame()` 不会将**字符串型**变量自动转换成**因子型**
```
用tibble创建数据框,不会这么麻烦,输出的就是原来的字符串类型
```{r tibble-5}
tibble(
a = 1:5,
b = letters[1:5]
)
```
我们有时候喜欢这样,构建两个有关联的变量, 比如
```{r tibble-6}
tb <- tibble(
x = 1:3,
y = x + 2
)
tb
```
但是,如果用传统的`data.frame()`来构建,会报错
```{r tibble-7, error = TRUE}
df <- data.frame(
x = 1:3,
y = x + 2
)
df
```
因此,在这一点上`tibble()`做的比较人性化。
大家还可以发现tibble另一个优势:tibble输出时,会显示多一行,用来指定每一列的类型。
tibble用缩写定义了7种类型:
| 类型 | 含义 |
|------|---------------------------|
| int | 代表integer |
| dbl | 代表double |
| chr | 代表character向量或字符串 |
| dttm | 代表日期+时间(date+time) |
| lgl | 代表逻辑判断TRUE或者FALSE |
| fctr | 代表因子类型factor |
| date | 代表日期dates |
## tibble数据操作
### 创建tibble
`tibble()`创建一个tibble类型的data.frame:
```{r tibble-8}
tibble(a = 1:5, b = letters[1:5])
```
刚才提到了,可以这样,
```{r tibble-9}
tibble(
a = 1:5,
b = 10:14,
c = a + b
)
```
- 为了让每列更加直观,也可以`tribble()`创建,数据量不大的时候,挺方便的
```{r tibble-10}
tribble(
~x, ~y, ~z,
"a", 2, 3.6,
"b", 1, 8.5
)
```
### 转换成tibble类型
转换成tibble类型意思就是说,刚开始不是tibble, 现在转换成tibble, 包括
- data.frame转换成tibble
- vector转换成tibble
- list转换成tibble
- matrix转换成tibble
#### data.frame转换成tibble
```{r tibble-11}
t1 <- iris[1:6, 1:4] # data.frame类型:
class(t1)
```
```{r tibble-12}
as_tibble(t1)
```
#### vector转型到tibble
```{r tibble-13}
x <- as_tibble(1:5) # Use `tibble::enframe()
x
```
#### 把list转型为tibble
```{r tibble-14}
df <- as_tibble(list(x = 1:6, y = runif(6), z = 6:1))
df
```
把tibble再转为list? `as.list(df)`
#### 把matrix转型为tibble。
```{r tibble-15}
m <- matrix(rnorm(15), ncol = 5)
as_tibble(m)
```
tibble转回matrix? `as.matrix(df)`
### tibble简单操作
构建一个简单的数据框
```{r tibble-16}
df <- tibble(
x = 1:2,
y = 2:1
)
df
```
增加一列
```{r tibble-17}
add_column(df, z = 0:1, w = 0)
```
增加一行
```{r tibble-18}
add_row(df, x = 99, y = 9)
```
在第二行,增加一行
```{r tibble-19}
add_row(df, x = 99, y = 9, .before = 2)
```
### 有用的函数`lst`
lst,创建一个list,具有tibble特性的list。
```{r tibble-20}
lst(n = 5, x = runif(n), y = TRUE)
```
### 有用的函数`enframe`
`enframe()`将矢量快速创建tibble,,创建的tibble只有2列: name和value
```{r tibble-21}
enframe(1:3)
```
```{r tibble-22}
enframe(c(a = 5, b = 7, c = 9))
```
### 有用的函数`deframe`
`deframe() `可以看做是`enframe()` 的反操作,把tibble反向转成向量
```{r tibble-23}
df <- enframe(c(a = 5, b = 7))
df
```
```{r tibble-24}
# 转为vector
deframe(df)
```
### 读取文件
read_csv()读取文件时,生成的直接就是tibble
```{r tibble-25}
read_csv("./demo_data/wages.csv")
```
## 关于行名
data.frame是支持行名的,但tibble不支持行名,**这也是两者不同的地方**
```{r tibble-26}
# 创建data.frame
df <- data.frame(x = 1:3, y = 3:1)
# 给df增加行名
row.names(df) <- LETTERS[1:3]
df
```
```{r tibble-27}
# 判断是否有行名
has_rownames(df)
```
但是对于tibble
```{r tibble-28, error=TRUE}
tb <- tibble(x = 1:3, y = 3:1)
row.names(tb) <- LETTERS[1:3]
```
```{block tibble-29, type="danger"}
需要注意的:
- 有时候遇到含有行名的data.frame,转换成tibble后,行名会被丢弃
- 如果想保留行名,就需要把行名转换成单独的一列
```
举个例子
```{r tibble-30}
df <- mtcars[1:3, 1:3]
df
```
```{r tibble-31}
# 把行名转换为单独的一列
rownames_to_column(df, var = "rowname")
```
```{r tibble-32}
# 把行索引转换为单独的一列
rowid_to_column(df, var = "rowid")
```
## 修复列名
规范的来说,数据框的列名应该是唯一。但现实中代码是人写的,因此可能会稀奇古怪的,所幸的是tibble也提供了**人性化的解决方案**
```{r tibble-33, error = TRUE}
tibble(x = 1, x = 2)
```
- `.name_repair = "check_unique"` 检查列名唯一性,但不做修复(默认)
- `.name_repair = "minimal"`, 不检查也不修复,维持现状
- `.name_repair = "unique"` 修复列名,使得列名唯一且不为空
- `.name_repair = "universal"` 修复列名,使得列名唯一且语法可读
具体使用方法:
```{r tibble-34}
tibble(x = 1, x = 2, .name_repair = "minimal")
```
```{r tibble-35}
tibble(x = 1, x = 2, .name_repair = "unique")
```
```{r tibble-36}
tibble(x = 1, x = 2, .name_repair = "universal")
```
```{r tibble-37}
tibble(`a 1` = 1, `a 2` = 2, .name_repair = "universal")
```
如果认为`x...1`, `x...2` 不符合自己的审美,可以指定修复函数
```{r tibble-38}
tibble(x = 1, x = 2, .name_repair = make.unique)
```
```{r tibble-39}
tibble(x = 1, x = 2, .name_repair = ~ make.unique(.x, sep = "_"))
```
```{r tibble-40}
tibble(x = 1, x = 2, .name_repair = ~ make.names(., unique = TRUE))
```
注意`make.unique(names, sep = ".")`和`make.names(names, unique = FALSE, allow_ = TRUE)` 是基础包的函数,可通过`?make.unique()`或者`make.names()`获取说明文档。
当然也可以自定义函数
```{r tibble-41}
fix_names <- function(x) gsub("\\s+", "_", x)
tibble(`year 1` = 1, `year 2` = 2, .name_repair = fix_names)
```
```{block tibble-42, type="danger"}
- 感觉越说越复杂了,事实上,我们写数据框的时候,完全可以避免上述问题,只要做到规范列名。
- 如果真正遇到比较乱的列名,推荐使用`janitor::clean_names()`一步到位。
```
```{r tibble-43}
library(janitor)
tibble(`year 1` = 1, `year 2` = 2) %>%
clean_names()
```
## nested tibble
`nested tibble` 和 `List-columns` (列表列) 会在后面的章节详细介绍。
```{r tibble-44}
iris %>%
group_by(Species) %>%
nest()
```
## 延伸阅读
1、阅读Hadley Wickham的[r4ds](https://r4ds.had.co.nz/)这本书[第10章](https://r4ds.had.co.nz/tibbles.html)。
2、 tibble的官方主页:[https://tibble.tidyverse.org/](https://tibble.tidyverse.org/)
3、创建**列表列**的方法,可以参考[nested tibble](https://tidyr.tidyverse.org/reference/nest.html)和
[list-columns](https://r4ds.had.co.nz/many-models.html)
```{r tibble-45, echo = F}
# remove the objects
rm(df, m, t1, tb, x, fix_names)
```
```{r tibble-46, echo = F, message = F, warning = F, results = "hide"}
pacman::p_unload(pacman::p_loaded(), character.only = TRUE)
```