提问人:azizi tamimi 提问时间:11/14/2023 最后编辑:moodymudskipperazizi tamimi 更新时间:11/14/2023 访问量:74
使用 pivot_longer() 将数据从宽数据转换为长数据
convert data from wide to long using pivot_longer()
问:
我需要您的帮助将数据从宽到长,将多个列/变量转换为行。
以下是数据。
stack1 <- tibble::tribble(
~ID, ~Recall1, ~Recall2, ~Recall3, ~Recall4, ~Recall5, ~Item1, ~Item2, ~Item3, ~Item4, ~Item5, ~vocab1, ~vocab2, ~vocab3, ~vocab4,
39, "Next", "His", "University", "Higher", "College", 1, 0, 1, 1, 0, 1, 1, 0, 1,
90, "Next", "her", "school", "Higher", "university", 1, 0, 1, 1, 0, 1, 1, 0, 1,
)
我想重新调整,使我只有三个变量:Recall_value Recog_score 和 vocab_sum。变量 vocab_sum 表示每个 ID 的 vocab1:vocab4 之和。
所需的输出应如下所示:
stack2 <- tibble::tribble(
~ID, ~Recall, ~Recall_value, ~Recog, ~Recog_score, ~vocab_sum,
39, "Recall1", "Next", "Item1", 1, 3,
39, "Recall2", "His", "Item2", 0, 3,
39, "Recall3", "University", "Item3", 1, 3,
39, "Recall4", "Higher", "Item4", 1, 3,
39, "Recall5", "College", "Item5", 0, 3,
90, "Recall1", "Next", "Item1", 1, 4,
90, "Recall2", "her", "Item2", 0, 4,
90, "Recall3", "school", "Item3", 1, 4,
90, "Recall4", "Higher", "Item4", 1, 4,
90, "Recall5", "university", "Item5", 0, 4,
)
我使用 pivot_longer() 尝试了以下代码:
> stack2 <- stack1 %>%
pivot_longer(
cols =c(`Recall1`:`Recall5`, `Item1`: `Item5`),
names_to = c("Recall","Recog"),
values_to = c("Recall_value", "Recog_score" ))
但是,它无助于实现预期的输出。
答:
0赞
Derf
11/14/2023
#1
您可以对 和 进行两个单独的透视。Recall
Item
cbind(
stack1 %>%
mutate(vocab_sum=vocab1+vocab2+vocab3+vocab4)%>%
select(-starts_with("vocab"),vocab_sum) %>%
pivot_longer(cols=starts_with("Recall"),
names_to="Recall",
values_to="Recall_value") %>%
select(-(Item1:Item5))
,
stack1 %>%
select(-starts_with("vocab")) %>%
pivot_longer(cols=starts_with("Item"),
names_to="Item",
values_to="Item_value") %>%
select(-(Recall1:Recall5),-ID)
) |> as_tibble()
# A tibble: 10 × 6
ID vocab_sum Recall Recall_value Item Item_value
<dbl> <dbl> <chr> <chr> <chr> <dbl>
1 39 3 Recall1 Next Item1 1
2 39 3 Recall2 His Item2 0
3 39 3 Recall3 University Item3 1
4 39 3 Recall4 Higher Item4 1
5 39 3 Recall5 College Item5 0
6 90 3 Recall1 Next Item1 1
7 90 3 Recall2 her Item2 0
8 90 3 Recall3 school Item3 1
9 90 3 Recall4 Higher Item4 1
10 90 3 Recall5 university Item5 0
评论
1赞
Mark
11/14/2023
一个小指针:可以用 代替,同样-vocab1,-vocab2,-vocab3,-vocab4
-starts_with("vocab")
Recall1:Recall5
0赞
Derf
11/14/2023
@Mark谢谢。我不情愿,因为它可能会被移除,但它可以在里面被覆盖vocab_sum
select()
0赞
Mark
11/14/2023
啊,对了,我错过了!或者,您可以使用 -vocab1:vocab4,就像在其他地方所做的那样。 也很棒.keep = "unused"
0赞
PGSA
11/14/2023
@Derf看到 Mark 的答案 - 由于一致的命名系统,通过使用参数和代词,可以在一个操作中透视到多个列。names_pattern
.value
names_to
0赞
Derf
11/14/2023
@PaulStaffordAllen 啊,是的,谢谢你的提示。忘了从我的答案中删除那部分。也没有注意到这一点,并且具有相同的编号。我看到了与 Mark at 类似的方法,但很难理解正则表达式部分Recall
Item
?pivot_longer
3赞
Mark
11/14/2023
#2
步骤:
- 通过对每行的所有词汇值求和来创建列。 然后删除所有这些词汇列,因为我们不再需要它们。
vocab_sum
.keep = "unused"
- 将非 ID 列或vocab_sum列(即 Recall 和 Item 列)透视更长时间,从其名称中捕获模式
library(tidyverse)
stack1 |>
mutate(vocab_sum = rowSums(across(starts_with("vocab"))), .keep = "unused") |>
pivot_longer(c(starts_with("Recall"), starts_with("Item")), names_to = c(".value", "Recall_num"), names_pattern = "(\\D+)(\\d+)")
输出:
# A tibble: 10 × 5
ID vocab_sum Recall_num Recall Item
<dbl> <dbl> <chr> <chr> <dbl>
1 39 3 1 Next 1
2 39 3 2 His 0
3 39 3 3 University 1
4 39 3 4 Higher 1
5 39 3 5 College 0
6 90 3 1 Next 1
7 90 3 2 her 0
8 90 3 3 school 1
9 90 3 4 Higher 1
10 90 3 5 university 0
我认为列顺序对您来说无关紧要,所以我在上面省略了它。但是,如果它很重要,则可以同时对列进行重新排序和重命名。select()
评论
1赞
Mark
11/14/2023
当然!所以那部分是正则表达式——正则表达式基本上是花哨的模式匹配
1赞
Mark
11/14/2023
\\d+ 一次或多次匹配一个数字 (0-9),\\D+ 一次或多次匹配任何不是数字的东西
1赞
Mark
11/14/2023
括号内的内容称为捕获组。它们由 names_to 使用(因此有两个值
1赞
Mark
11/14/2023
正则表达式可能有点像看一个神秘的代码,但它们非常适合简明扼要地描述你想要的东西
1赞
Mark
11/14/2023
regex101.com/r/dVA1I9/1
评论