如何解决R tidyverse如何互相做两个pivot_longer而不是一个
假设以下数据:
structure(list(uuid = c("abc","def","hij"),Q1r1 = c(0L,1L,1L),Q1r2 = c(1L,Q1r3 = c(1L,0L,Q2r1c1 = c(4L,3L,5L),Q2r1c2 = 2:4,Q2r1c3 = c(1L,5L,2L),Q2r2c1 = c(3L,4L),Q2r2c2 = c(2L,Q2r2c3 = c(1L,4L,Q3r1 = c(5L,9L,7L),Q3r2 = c(10L,8L),Q3r3 = c(6L,8L,5L)),class = "data.frame",row.names = c(NA,-3L))
给出:
uuid Q1r1 Q1r2 Q1r3 Q2r1c1 Q2r1c2 Q2r1c3 Q2r2c1 Q2r2c2 Q2r2c3 Q3r1 Q3r2 Q3r3
1 abc 0 1 1 4 2 1 3 2 1 5 10 6
2 def 1 1 0 3 3 5 3 5 4 9 3 8
3 hij 1 1 1 5 4 2 4 4 5 7 8 5
现在假设我想对所有Q1和Q3列的数据都进行透视处理(其中这些列中的r1,r2和r3表示要创建的行)。
这相对简单:
dat %>%
pivot_longer(cols = c(starts_with("Q1"),starts_with("Q3")), names_sep = "r", names_to = c('.value','brand’))
给出:
# A tibble: 9 x 10
uuid Q2r1c1 Q2r1c2 Q2r1c3 Q2r2c1 Q2r2c2 Q2r2c3 brand Q1 Q3
<chr> <int> <int> <int> <int> <int> <int> <chr> <int> <int>
1 abc 4 2 1 3 2 1 1 0 5
2 abc 4 2 1 3 2 1 2 1 10
3 abc 4 2 1 3 2 1 3 1 6
4 def 3 3 5 3 5 4 1 1 9
5 def 3 3 5 3 5 4 2 1 3
6 def 3 3 5 3 5 4 3 0 8
7 hij 5 4 2 4 4 5 1 1 7
8 hij 5 4 2 4 4 5 2 1 8
9 hij 5 4 2 4 4 5 3 1 5
现在,这是我的问题:是否还会有一种方法将两个枢轴彼此分开,即首先是pivot_longer Q1,然后是pivot_longer Q3?
我要问的原因是,我也想透视Q2和Q3(但是在Q2中,行标识符为c1,c2,c3,并且我想在pivoting_longer之后有两个结果列Q2r1和Q2r2,而该行Q3的标识符是r1,r2,r3,因此上面带有names_sep
和names_to
的简单代码不再起作用)。一位同事告诉我,在其他软件中,您可以将单个pivot_longers连接起来,因此我想知道在R中是否可以做到这一点。
注意:我知道如何在一轮中完成Q2和Q3的数据透视。我真的只是想知道是否有可能拆分枢轴并依次进行。
我将围绕Q1和Q3的第一个示例的预期输出为:
# A tibble: 9 x 10
uuid Q2r1c1 Q2r1c2 Q2r1c3 Q2r2c1 Q2r2c2 Q2r2c3 brand Q1 Q3
<chr> <int> <int> <int> <int> <int> <int> <chr> <int> <int>
1 abc 4 2 1 3 2 1 1 0 5
2 abc 4 2 1 3 2 1 2 1 10
3 abc 4 2 1 3 2 1 3 1 6
4 def 3 3 5 3 5 4 1 1 9
5 def 3 3 5 3 5 4 2 1 3
6 def 3 3 5 3 5 4 3 0 8
7 hij 5 4 2 4 4 5 1 1 7
8 hij 5 4 2 4 4 5 2 1 8
9 hij 5 4 2 4 4 5 3 1 5
第二个示例中我想在Q2和Q3上显示的期望输出是:
# A tibble: 9 x 8
uuid Q1r1 Q1r2 Q1r3 brand Q2r1 Q2r2 Q3
<chr> <int> <int> <int> <chr> <int> <int> <int>
1 abc 0 1 1 brand1 4 3 5
2 abc 0 1 1 brand2 2 2 10
3 abc 0 1 1 brand3 1 1 6
4 def 1 1 0 brand1 3 3 9
5 def 1 1 0 brand2 3 5 3
6 def 1 1 0 brand3 5 4 8
7 hij 1 1 1 brand1 5 4 7
8 hij 1 1 1 brand2 4 4 8
9 hij 1 1 1 brand3 2 5 5
解决方法
好吧,在更好地理解了问题之后,我能想到的唯一答案是黑手党。您在评论中提到了一个。这是另一个。这围绕着使用灵活的正则表达式来选择列。然后,它通过Reduce()
将数据帧连接在一起(或者如果愿意,可以将purrr::reduce()
交换)。另外,请注意,这是执行从宽到长的多个独立时间(并合并),而不是依次执行。
col_starts <- c("Q2","Q3")
lapply(col_starts,function(x) {
df %>%
pivot_longer(matches(paste0("^",x)),names_pattern = "(Q\\d.*)[rc](\\d)$",names_to = c(".value","brand")) %>%
select(uuid,brand:ncol(.),everything(),-matches(paste0("^",setdiff(col_starts,x),collapse = "|")))
}) %>% Reduce(function(x,y) left_join(x,y,by = intersect(names(x),names(y))),.)
# A tibble: 9 x 8
uuid brand Q2r1 Q2r2 Q1r1 Q1r2 Q1r3 Q3
<chr> <chr> <int> <int> <int> <int> <int> <int>
1 abc 1 4 3 0 1 1 5
2 abc 2 2 2 0 1 1 10
3 abc 3 1 1 0 1 1 6
4 def 1 3 3 1 1 0 9
5 def 2 3 5 1 1 0 3
6 def 3 5 4 1 1 0 8
7 hij 1 5 4 1 1 1 7
8 hij 2 4 4 1 1 1 8
9 hij 3 2 5 1 1 1 5
这里是一个仅保留uuid
,brand
和派生列的版本(读取imo有点容易)
lapply(c("Q2","Q3"),brand,starts_with(x))
}) %>% Reduce(function(x,by = c("uuid","brand")),.)
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。