R语言学习笔记(5)——数据重塑

R语言中的数据重塑是关于改变数据被组织成行和列的方式。 大多数时间R语言中的数据处理是通过将输入数据作为数据帧来完成的。 很容易从数据帧的行和列中提取数据,但是在某些情况下,我们需要的数据帧格式与我们接收数据帧的格式不同。 R语言具有许多功能,在数据帧中拆分,合并和将行更改为列,反之亦然。

在数据帧中加入列和行

使用函数cbind()

  1. 连接多个向量来创建数据帧
  2. 合并两个数据帧

连接多个向量来创建数据帧:

> # 创建一个向量对象.
> city <- c("Tampa","Seattle","Hartford","Denver")
> state <- c("FL","WA","CT","CO")
> zipcode <- c(33602,98104,06161,80294)
> 
> # 将三个向量合并成一个数据帧.
> addresses <- cbind(city,state,zipcode)
> 
> cat("# # # # The First data frame
+ ") 
> 
> # 打印数据帧.
> print(addresses)

输出:

# # # # The First data frame
     city       state zipcode
[1,] "Tampa"    "FL"  "33602"
[2,] "Seattle"  "WA"  "98104"
[3,] "Hartford" "CT"  "6161" 
[4,] "Denver"   "CO"  "80294"

合并两个数据帧:

# 创建另一个具有相同行的数据帧
new.address <- data.frame(
   city = c("Lowry","Charlotte"),
   state = c("CO","FL"),
   zipcode = c("80230","33949"),
   stringsAsFactors = FALSE
)

cat("# # # The Second data frame
") 

# 打印这个数据帧.
print(new.address)

# 合并两个数据帧.
all.addresses <- rbind(addresses,new.address)

cat("# # # The combined data frame
") 

# 输出合并后的数据帧.
print(all.addresses)

输出:

# # # The Second data frame
       city       state   zipcode
1      Lowry      CO      80230
2      Charlotte  FL      33949

# # # The combined data frame
       city      state zipcode
1      Tampa     FL    33602
2      Seattle   WA    98104
3      Hartford  CT     6161
4      Denver    CO    80294
5      Lowry     CO    80230
6     Charlotte  FL    33949

注:
本例中创建第二个数据帧时用到了参数 stringsAsFactors = FALSE ,这是为了避免将字符型转换成因子(R语言在创建数据帧时默认将 character 当成 factor)。当然,不加此参数对于本例的输出无影响,但若后续需要对我们认为的字符型进行操作时则需加上此参数。

合并数据帧

使用merge()函数合并两个数据帧。 数据帧必须具有相同的列名称,在其上进行合并。
在下面的例子中,我们考虑图书馆名称“MASS”中有关Pima Indian Women的糖尿病的数据集。 我们基于血压(“bp”)和体重指数(“bmi”)的值合并两个数据集。 在选择这两列用于合并时,其中这两个变量的值在两个数据集中匹配的记录被组合在一起以形成单个数据帧。

library(MASS)
merged.Pima <- merge(x = Pima.te, y = Pima.tr,
   by.x = c("bp", "bmi"),
   by.y = c("bp", "bmi")
   #指定两个数据框中匹配列名称,
   #默认情况下使用两个数据框中相同列名称。
)
print(merged.Pima)
nrow(merged.Pima)

输出:

   bp  bmi npreg.x glu.x skin.x ped.x age.x type.x npreg.y glu.y skin.y ped.y age.y type.y
1  60 33.8       1   117     23 0.466    27     No       2   125     20 0.088    31     No
2  64 29.7       2    75     24 0.370    33     No       2   100     23 0.368    21     No
3  64 31.2       5   189     33 0.583    29    Yes       3   158     13 0.295    24     No
4  64 33.2       4   117     27 0.230    24     No       1    96     27 0.289    21     No
5  66 38.1       3   115     39 0.150    28     No       1   114     36 0.289    21     No
6  68 38.5       2   100     25 0.324    26     No       7   129     49 0.439    43    Yes
7  70 27.4       1   116     28 0.204    21     No       0   124     20 0.254    36    Yes
8  70 33.1       4    91     32 0.446    22     No       9   123     44 0.374    40     No
9  70 35.4       9   124     33 0.282    34     No       6   134     23 0.542    29    Yes
10 72 25.6       1   157     21 0.123    24     No       4    99     17 0.294    28     No
11 72 37.7       5    95     33 0.370    27     No       6   103     32 0.324    55     No
12 74 25.9       9   134     33 0.460    81     No       8   126     38 0.162    39     No
13 74 25.9       1    95     21 0.673    36     No       8   126     38 0.162    39     No
14 78 27.6       5    88     30 0.258    37     No       6   125     31 0.565    49    Yes
15 78 27.6      10   122     31 0.512    45     No       6   125     31 0.565    49    Yes
16 78 39.4       2   112     50 0.175    24     No       4   112     40 0.236    38     No
17 88 34.5       1   117     24 0.403    40    Yes       4   127     11 0.598    28     No
[1] 17

注:
其实在R语言图书馆名称“MASS”中有关Pima Indian Women的糖尿病的数据集对于 x=Pima.te ,其中的数据就有332行,之所以输出只有17行,是因为其与 y=Pima.tr 进行了合并。
即此例中的合并是通过对比 x 与 y 中的血压(“bp”)和体重(“bmi”),然后将二者中这两个变量完全相同的数据帧合并为一个数据帧,而其他参数被依次保留。故在合并的数据帧中血压(“bp”)和体重(“bmi”)这两个变量是没有 x 与 y 之分的,其他变量有。

拆分数据与数据重构

通过函数melt()拆分数据,函数cast()数据重构,在多个步骤中改变数据的形状以获得期望的形状。
我们考虑称为船舶的数据集称为“MASS”。

> library(MASS)
> print(ships)

输出:

   type year period service incidents
1     A   60     60     127         0
2     A   60     75      63         0
3     A   65     60    1095         3
4     A   65     75    1095         4
5     A   70     60    1512         6
6     A   70     75    3353        18
7     A   75     60       0         0
8     A   75     75    2244        11
9     B   60     60   44882        39
10    B   60     75   17176        29
11    B   65     60   28609        58
12    B   65     75   20370        53
13    B   70     60    7064        12
14    B   70     75   13099        44
15    B   75     60       0         0
16    B   75     75    7117        18
17    C   60     60    1179         1
18    C   60     75     552         1
19    C   65     60     781         0
20    C   65     75     676         1
21    C   70     60     783         6
22    C   70     75    1948         2
23    C   75     60       0         0
24    C   75     75     274         1
25    D   60     60     251         0
26    D   60     75     105         0
27    D   65     60     288         0
28    D   65     75     192         0
29    D   70     60     349         2
30    D   70     75    1208        11
31    D   75     60       0         0
32    D   75     75    2051         4
33    E   60     60      45         0
34    E   60     75       0         0
35    E   65     60     789         7
36    E   65     75     437         7
37    E   70     60    1157         5
38    E   70     75    2161        12
39    E   75     60       0         0
40    E   75     75     542         1

melt()拆分数据

现在我们拆分数据进行重组,将除类型和年份以外的所有列转换为多行展示。

install.packages("reshape")
library(reshape)
molten.ships <- melt(ships, id = c("type","year"))
print(molten.ships)

注:
因我使用的 R 4.2.2 直接运行第三行与第四行代码出现报错:
package ‘reshape’ is not available for this version of R
故选择先从CRAN网页获取软件包,并将软件包安装在R环境中(笔记(4)——包中有介绍)。再运行第三行与第四行代码。
结果(3×40=120行):

    type year  variable value
1      A   60    period    60
2      A   60    period    75
3      A   65    period    60
4      A   65    period    75
5      A   70    period    60
6      A   70    period    75
7      A   75    period    60
8      A   75    period    75
9      B   60    period    60
10     B   60    period    75
11     B   65    period    60
12     B   65    period    75
13     B   70    period    60
14     B   70    period    75
15     B   75    period    60
16     B   75    period    75
17     C   60    period    60
18     C   60    period    75
19     C   65    period    60
20     C   65    period    75
21     C   70    period    60
22     C   70    period    75
23     C   75    period    60
24     C   75    period    75
25     D   60    period    60
26     D   60    period    75
27     D   65    period    60
28     D   65    period    75
29     D   70    period    60
30     D   70    period    75
31     D   75    period    60
32     D   75    period    75
33     E   60    period    60
34     E   60    period    75
35     E   65    period    60
36     E   65    period    75
37     E   70    period    60
38     E   70    period    75
39     E   75    period    60
40     E   75    period    75
41     A   60   service   127
42     A   60   service    63
43     A   65   service  1095
44     A   65   service  1095
45     A   70   service  1512
46     A   70   service  3353
47     A   75   service     0
48     A   75   service  2244
49     B   60   service 44882
50     B   60   service 17176
51     B   65   service 28609
52     B   65   service 20370
53     B   70   service  7064
54     B   70   service 13099
55     B   75   service     0
56     B   75   service  7117
57     C   60   service  1179
58     C   60   service   552
59     C   65   service   781
60     C   65   service   676
61     C   70   service   783
62     C   70   service  1948
63     C   75   service     0
64     C   75   service   274
65     D   60   service   251
66     D   60   service   105
67     D   65   service   288
68     D   65   service   192
69     D   70   service   349
70     D   70   service  1208
71     D   75   service     0
72     D   75   service  2051
73     E   60   service    45
74     E   60   service     0
75     E   65   service   789
76     E   65   service   437
77     E   70   service  1157
78     E   70   service  2161
79     E   75   service     0
80     E   75   service   542
81     A   60 incidents     0
82     A   60 incidents     0
83     A   65 incidents     3
84     A   65 incidents     4
85     A   70 incidents     6
86     A   70 incidents    18
87     A   75 incidents     0
88     A   75 incidents    11
89     B   60 incidents    39
90     B   60 incidents    29
91     B   65 incidents    58
92     B   65 incidents    53
93     B   70 incidents    12
94     B   70 incidents    44
95     B   75 incidents     0
96     B   75 incidents    18
97     C   60 incidents     1
98     C   60 incidents     1
99     C   65 incidents     0
100    C   65 incidents     1
101    C   70 incidents     6
102    C   70 incidents     2
103    C   75 incidents     0
104    C   75 incidents     1
105    D   60 incidents     0
106    D   60 incidents     0
107    D   65 incidents     0
108    D   65 incidents     0
109    D   70 incidents     2
110    D   70 incidents    11
111    D   75 incidents     0
112    D   75 incidents     4
113    E   60 incidents     0
114    E   60 incidents     0
115    E   65 incidents     7
116    E   65 incidents     7
117    E   70 incidents     5
118    E   70 incidents    12
119    E   75 incidents     0
120    E   75 incidents     1

cast()重构数据

我们可以将被拆分的数据转换为一种新形式,使用cast()函数创建每年每种类型的船的总和。

> recasted.ship <- cast(molten.ships, type+year~variable,sum)
> #cast(合并的数据帧,重塑的数据的格式;类似 x ~ y 格式,x 为行标签,y 为列标签;聚合函数,用于对数据值进行处理)
> print(recasted.ship)

结果:

   type year period service incidents
1     A   60    135     190         0
2     A   65    135    2190         7
3     A   70    135    4865        24
4     A   75    135    2244        11
5     B   60    135   62058        68
6     B   65    135   48979       111
7     B   70    135   20163        56
8     B   75    135    7117        18
9     C   60    135    1731         2
10    C   65    135    1457         1
11    C   70    135    2731         8
12    C   75    135     274         1
13    D   60    135     356         0
14    D   65    135     480         0
15    D   70    135    1557        13
16    D   75    135    2051         4
17    E   60    135      45         0
18    E   65    135    1226        14
19    E   70    135    3318        17
20    E   75    135     542         1

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

HanWLang

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值