我有一个超过3000个工作的数据帧。它看起来像这样:
dat <- data.frame(
letter = rep(c("A", "B", "C"), each=4),
numbers = rep(seq(1,1.75, by=0.25), 3)
)
dat
# letter numbers
# 1 A 1.00
# 2 A 1.25
# 3 A 1.50
# 4 A 1.75
# 5 B 1.00
# 6 B 1.25
# 7 B 1.50
# 8 B 1.75
# 9 C 1.00
# 10 C 1.25
# 11 C 1.50
# 12 C 1.75
我想重新排列这个数据帧,使它看起来像:
# A B C
# 1 1.00 1.00 1.00
# 2 1.25 1.25 1.25
# 3 1.50 1.50 1.50
# 4 1.75 1.75 1.75
无需手动硬编码所有3,000个观测值。
在所有的工具,我已经-可能不正确-尝试到目前为止(重塑,分裂,group_split,突变%>%分裂%>% unnest, pivot_wider,和dcast)分裂给出了最接近的输出,我试图实现(见下面),但我不确定如何索引数据框架内嵌套的数据框架的特定列,我不确定如何重新组合单个数据框架,而不连接它们。也就是说,我想保持每个字母下的所有值彼此独立。
spldf <- split(dat, dat$letter)
spldf
# $A
# letter numbers
# 1 A 1.00
# 2 A 1.25
# 3 A 1.50
# 4 A 1.75
#
# $B
# letter numbers
# 5 B 1.00
# 6 B 1.25
# 7 B 1.50
# 8 B 1.75
#
# $C
# letter numbers
# 9 C 1.00
# 10 C 1.25
# 11 C 1.50
# 12 C 1.75
我已经看了S.O. 2天了,还没有看到一个问题相似到足以让我复制它。我感谢任何帮助这个问题!
如果'letter'列的元素数相同,我们可以从base R
中使用unstack
unstack(dat, numbers ~ letter)
与产出
# A B C
#1 1.00 1.00 1.00
#2 1.25 1.25 1.25
#3 1.50 1.50 1.50
#4 1.75 1.75 1.75
但是,如果数据真的很大,长度不等的可能性就更大。在这种情况下,我们需要一个序列列,以确保如果有较小的长度,可以用NA
library(dplyr)
library(tidyr)
library(data.table)
dat %>%
mutate(rn = rowid(letter)) %>%
pivot_wider(names_from = letter, values_from = numbers) %>%
select(-rn)
使用dcast
的data.table
选项
dcast(setDT(dat),rowid(letter)~letter,value.var = "numbers")[,-1]
为
A B C
1: 1.00 1.00 1.00
2: 1.25 1.25 1.25
3: 1.50 1.50 1.50
4: 1.75 1.75 1.75
您仍然可以在tidyverse框架中这样做,但是您需要添加一个id变量来标记字母中的数字序列。
library(tidyverse)
dat <- data.frame(
letter = rep(c("A", "B", "C"), each=4),
numbers = rep(seq(1,1.75, by=0.25), 3)
)
dat%>% group_by(letter)%>%
mutate(id=1:n()) %>%
pivot_wider(id_cols=id,
names_from = letter,
values_from=numbers) %>%
select(-id)
#> # A tibble: 4 x 3
#> A B C
#> <dbl> <dbl> <dbl>
#> 1 1 1 1
#> 2 1.25 1.25 1.25
#> 3 1.5 1.5 1.5
#> 4 1.75 1.75 1.75
由reprex包(v0.3.0)创建于2021-02-10