使用group by 数据变慢_R 语言一次合并多组数据以及长宽数据转换

本文详细介绍R语言中数据合并的方法,包括使用merge函数及tidyverse包中的full_join等函数进行不同情况的数据合并,并演示如何利用gather、pivot_longer等函数实现数据的长宽转换。
摘要由CSDN通过智能技术生成

5830ceb9264ce34569df3e2bdfceb7a2.png

现在是 2020 年 1 月 12 日:

参考链接:

  • Merging a lot of data.frames [duplicate]
  • merge.html

当列名相同时

第一种方法:

df1 = data.frame(id = c('1','73','2','10','43'),
                 v1 = c(1,2,3,4,5)) 
df1
df2 = data.frame(id = c('7','23','57','2','62','96'),
                 v2 = c(1,2,3,4,5,6)) 
df2
df3 = data.frame(id = c('23','62'),
                 v3 = c(1,2)) 
df3

Reduce(function(x, y) merge(x, y, all=TRUE),
       list(df1, df2, df3))
   id v1 v2 v3
1   1  1 NA NA
2  10  4 NA NA
3   2  3  4 NA
4  43  5 NA NA
5  73  2 NA NA
6  23 NA  2  1
7  57 NA  3 NA
8  62 NA  5  2
9   7 NA  1 NA
10 96 NA  6 NA

# 或者
Reduce(function(...) merge(..., all=TRUE),
       list(df1, df2, df3))

# 其实上面拆开就是拆开就是
merge(merge(df1, df2, by = 'id', all = T), df3, 
      by = 'id', all = T)

第二种方法:

插曲:
动态图见:R 语言中 dplyr 包 jion 函数之目前我看到过的最形象的教程
  • inner_join(): 相当于交集
  • left_join():字面意思,左连接;保留 x 中的所有观测
  • right_join():右连接;保留 y 中的所有观测
  • full_join():全连接;保留 x 和 y 中的所有观测
  • semi_join():保留 x 表中与 y 表中的观测相匹配的所有观测
  • anti_join():丢弃 x 表中与 y 表中的观测相匹配的所有观测。

b73b6a1a73c286bb8e29686b520acc2e.png
library(tidyverse)
df1 %>%
  full_join(df2, by = "id") %>%
  full_join(df3, by = "id")

   id v1 v2 v3
1   1  1 NA NA
2  73  2 NA NA
3   2  3  4 NA
4  10  4 NA NA
5  43  5 NA NA
6   7 NA  1 NA
7  23 NA  2  1
8  57 NA  3 NA
9  62 NA  5  2
10 96 NA  6 NA

当列名不同?

当我们所需要合并的列的列名不一样时候, 第一种方法可能就不够用了,或者说要进行修改。

但是第二种方法仍然有效

library(tidyverse)
df1 %>%
  full_join(df2, by = c("id" = "id1")) %>% # id 为数据 df1 所要合并的列,id1 是 df2 所要合并的列
  full_join(df3, by = c("id" = "id2"))

   id v1 v2 v3
1   1  1 NA NA
2  73  2 NA NA
3   2  3  4 NA
4  10  4 NA NA
5  43  5 NA NA
6   7 NA  1 NA
7  23 NA  2  1
8  57 NA  3 NA
9  62 NA  5  2
10 96 NA  6 NA

如果我们使用 merge() 函数呢?

library(tidyverse)
merge(df1, df2, by.x = "id", by.y = "id1", all = TRUE) %>%
  merge(., df3, by.x = "id", by.y = "id2", all = TRUE)

   id v1 v2 v3
1   1  1 NA NA
2  10  4 NA NA
3   2  3  4 NA
4  43  5 NA NA
5  73  2 NA NA
6  23 NA  2  1
7  57 NA  3 NA
8  62 NA  5  2
9   7 NA  1 NA
10 96 NA  6 NA

# 或者不借助管道,因为都用管道符号了那直接用 full_join() 系列函数不就行了?
merge(merge(df1, df2, by.x = "id", by.y = "id1", all = TRUE), df3,
      by.x = "id", by.y = "id2", all = TRUE)

   id v1 v2 v3
1   1  1 NA NA
2  10  4 NA NA
3   2  3  4 NA
4  43  5 NA NA
5  73  2 NA NA
6  23 NA  2  1
7  57 NA  3 NA
8  62 NA  5  2
9   7 NA  1 NA
10 96 NA  6 NA

既然提到了数据合并,那就顺带提一下数据的 长边宽宽变长

宽变长和长变宽

参考链接(请花点时间都看下):
  • R mini camp: Reshape2 and Tidyr
  • Pivoting data frames just got easier thanks to `pivot_wide()` and pivot_long() : 不知道为啥链接函数名改了。

宽变长

  • gather()
  • melt()
  • pivot_longer()
# melt()
# id.vars 表示不变的列,如:id.vars = c("year", "month")
# measure.vars 表示要变的列
# variable.name 表示你分组后的 group 列名,即下面的 variable
# value.name 表示对应的值的列名
# na.rm 表示是否去除 NA 值的行

data_long <- reshape2::melt(merge_data,
               measure.vars = c('v1','v2','v3'),
               variable.name = "test_group",
               value.name = "test_value")
data_long
   id test_group test_value
1   1         v1          1
2  10         v1          4
3   2         v1          3
4  43         v1          5
5  73         v1          2
6  23         v1         NA
7  57         v1         NA
8  62         v1         NA
9   7         v1         NA
10 96         v1         NA
11  1         v2         NA
12 10         v2         NA
13  2         v2          4
14 43         v2         NA
15 73         v2         NA
16 23         v2          2
17 57         v2          3
18 62         v2          5
19  7         v2          1
20 96         v2          6
21  1         v3         NA
22 10         v3         NA
23  2         v3         NA
24 43         v3         NA
25 73         v3         NA
26 23         v3          1
27 57         v3         NA
28 62         v3          2
29  7         v3         NA
30 96         v3         NA

# gather()
# gather(data, key = "key", value = "value", ..., na.rm = FALSE, 
#        convert = FALSE, factor_key = FALSE)
data_long1 <- tidyr::gather(merge_data, 
                            test_group, test_value, 要生成的新列的 group 列名和值列名
                            -id) # 不变的列,其他的都变,多列不变就多 -a, -b

data_long1
   id test_group test_value
1   1         v1          1
2  10         v1          4
3   2         v1          3
4  43         v1          5
5  73         v1          2
6  23         v1         NA
7  57         v1         NA
8  62         v1         NA
9   7         v1         NA
10 96         v1         NA
11  1         v2         NA
12 10         v2         NA
13  2         v2          4
14 43         v2         NA
15 73         v2         NA
16 23         v2          2
17 57         v2          3
18 62         v2          5
19  7         v2          1
20 96         v2          6
21  1         v3         NA
22 10         v3         NA
23  2         v3         NA
24 43         v3         NA
25 73         v3         NA
26 23         v3          1
27 57         v3         NA
28 62         v3          2
29  7         v3         NA
30 96         v3         NA

# pivot_longer
# devtools::install_github("tidyverse/tidyr")
# library(tidyverse)
data_long1 <- data_wide %>% 
  tidyr::pivot_longer(cols = c("v1", "v2", "v3"), # 变的列,也就是即将合并为一列的列
                        names_to = "test_group", # 表示你分组后的 group 列名,即 cols 合并后的列名
                        values_to = "test_value") # 表示对应的值的列名
data_long1
# A tibble: 30 x 3
   id    test_group test_value
   <fct> <chr>           <dbl>
 1 1     v1                  1
 2 1     v2                 NA
 3 1     v3                 NA
 4 10    v1                  4
 5 10    v2                 NA
 6 10    v3                 NA
 7 2     v1                  3
 8 2     v2                  4
 9 2     v3                 NA
10 43    v1                  5
# … with 20 more rows

长变宽

  • spread()
  • dcast()
  • pivot_wider()
# dcast
# dcast(data, formula, fun.aggregate = NULL, ..., margins = NULL,
  subset = NULL, fill = NULL, drop = TRUE,
  value.var = guess_value(data))

# id ~ test_group:将为新的 group 列 + group 列
# fun.aggregate:可以复制数据处理处理函数功能:mean,max等等
reshape2::dcast(data_long, id ~ test_group)
   id v1 v2 v3
1   1  1 NA NA
2  10  4 NA NA
3   2  3  4 NA
4  43  5 NA NA
5  73  2 NA NA
6  23 NA  2  1
7  57 NA  3 NA
8  62 NA  5  2
9   7 NA  1 NA
10 96 NA  6 NA


# spread()
# spread(data, key, value, fill = NA, convert = FALSE, drop = TRUE, sep = NULL)

tidyr::spread(data_long1, "test_group", "test_value")
   id v1 v2 v3
1   1  1 NA NA
2  10  4 NA NA
3   2  3  4 NA
4  43  5 NA NA
5  73  2 NA NA
6  23 NA  2  1
7  57 NA  3 NA
8  62 NA  5  2
9   7 NA  1 NA
10 96 NA  6 NA

# pivot_wider

data_wide <- data_long %>% 
  tidyverse::pivot_wider(names_from = "test_group", 
                        values_from = "test_value") 
 data_wide
# A tibble: 10 x 4
   id       v1    v2    v3
   <fct> <dbl> <dbl> <dbl>
 1 1         1    NA    NA
 2 10        4    NA    NA
 3 2         3     4    NA
 4 43        5    NA    NA
 5 73        2    NA    NA
 6 23       NA     2     1
 7 57       NA     3    NA
 8 62       NA     5     2
 9 7        NA     1    NA
10 96       NA     6    NA

既然提到了上面,那么就再顺带提一下将一列分割?

参考链接: How to reshape data in R: tidyr vs reshape2

  • separate()
  • aggregate (): 很有用,以后补上

部分参考:《 R 数据科学 》

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值