我有一个类似于以下的df:
df <- data.frame("name" = c("sue","joe","tom"),
"x0_date" = c("2020-1-20", "2020-2-20", "2020-3-20"),
"x0_class" = c("biology", "physics", "chemistry"),
"x1_date" = c("2021-4-18", NA, "2021-6-18"),
"x1_class" = c("english", NA, "drama"))
df
name x0_date x0_class x1_date x1_class
1 sue 2020-1-20 biology 2021-4-18 english
2 joe 2020-2-20 physics <NA> <NA>
3 tom 2020-3-20 chemistry 2021-6-18 drama
我正在努力调整更长的时间,这样我的结果如下:
name date class
1 sue 2020-1-20 biology
2 sue 2021-4-18 english
3 joe 2020-2-20 physics
4 tom 2020-3-20 chemistry
5 tom 2021-6-18 drama
我想我只在某些数据是数字的时候才进行过数据透视,所以我遇到了麻烦。我试过这样的东西:
test <- df %>%
pivot_longer(matches("date|class"),
names_to = c("date", "class"),
names_pattern = "(\d+)_(.+)",
values_drop_na = TRUE)
但产出并不完全正确。如果相关的话,我的宽数据是非常宽的("x0"到"x_400"(。感谢您的帮助!
我们需要names_to
作为.value
。根据?pivot_longer
names_to-如果长度>1,将创建多个列。在这种情况下,必须提供names_sep或names_pattern中的一个来指定如何拆分列名。还有两个额外的字符值可以利用:
NA将丢弃列名的相应组件。
"。值";指示列名的相应组件定义包含单元格值的输出列的名称,完全覆盖values_to。
因此,将其指定为.value
,并使用names_pattern
仅捕获_
之后的字符,即(_(.*)
(
library(dplyr)
library(tidyr)
df %>%
pivot_longer(cols = -name, names_to = c(".value"),
names_pattern = ".*_(.*)", values_drop_na = TRUE)
-输出
# A tibble: 5 × 3
name date class
<chr> <chr> <chr>
1 sue 2020-1-20 biology
2 sue 2021-4-18 english
3 joe 2020-2-20 physics
4 tom 2020-3-20 chemistry
5 tom 2021-6-18 drama
如果我们需要x0
、x1
前缀作为另一列,那么我们需要为前缀指定列名,还需要捕获前缀部分
df %>%
pivot_longer(cols = -name, names_to = c("categ", ".value"),
names_pattern = "(.*)_(.*)", values_drop_na = TRUE)
-输出
# A tibble: 5 × 4
name categ date class
<chr> <chr> <chr> <chr>
1 sue x0 2020-1-20 biology
2 sue x1 2021-4-18 english
3 joe x0 2020-2-20 physics
4 tom x0 2020-3-20 chemistry
5 tom x1 2021-6-18 drama
OP代码不起作用的原因
df %>%
+ pivot_longer(matches("date|class"),
+ names_to = c("date", "class"),
+ names_pattern = "(\d+)_(.+)",
+ values_drop_na = TRUE)
# A tibble: 10 × 4
name date class value
<chr> <chr> <chr> <chr>
1 sue 0 date 2020-1-20
2 sue 0 class biology
3 sue 1 date 2021-4-18
4 sue 1 class english
5 joe 0 date 2020-2-20
6 joe 0 class physics
7 tom 0 date 2020-3-20
8 tom 0 class chemistry
9 tom 1 date 2021-6-18
10 tom 1 class drama
是因为它捕获了_
之前的一个或多个数字(\d+
(,然后将其余的(.+
(作为列前缀和后缀,因此我们从"date"中的"x0"、"x1"one_answers"class"中的后缀部分获得了0,1,由于我们没有指定.value
,默认列value
将返回列的值
- 我们可以通过将
df
拆分为列名为name , data , class
的data.frame
列表来使用Base R
rbind
函数
lapply(1:((ncol(df)-1)/2) , (i) df[c(1,2*i,2*i+1)]) |>
lapply((x) {colnames(x) <- c("name" , "data" , "class") ; x}) |>
do.call(rbind , args = _) |> na.omit()
- 输出
name data class
1 sue 2020-1-20 biology
2 joe 2020-2-20 physics
3 tom 2020-3-20 chemistry
4 sue 2021-4-18 english
6 tom 2021-6-18 drama