我在R中有一个数据帧,看起来类似于以下内容:
A B C
A X 1
A Y 3
A Z 3
A Z 2
如果所有列都包含因子而不是字符串或整数,我如何将单列"C"转换为与B中的值相对应的多列?
我想要如下所示的内容,无论是否在数据帧中保留B/C列。
A B C X Y Z
A X 1 1 NA NA
A Y 3 NA 3 NA
A Z 3 NA NA 3
A Z 2 NA NA 2
理想情况下,我希望我的最终输出是R中的一个数据帧,因为我打算将它与另一个具有匹配值a值的数据帧合并。
如果这篇帖子重复,我很抱歉,但我没有发现任何地方可以告诉别人在问同样的问题。-谢谢
这里有两种tidyverse
方式,我承认它们有点笨拙。它们都使用tidyr::spread
来获得宽形状的数据,然后将宽版本绑定回原始版本。
library(tidyr)
library(dplyr)
要使用spread
,首先需要对每一行进行某种标识。一个快速的方法是使用tibble::rowid_to_column
。
df %>%
tibble::rowid_to_column() %>%
spread(key = B, value = C)
#> rowid A X Y Z
#> 1 1 A 1 NA NA
#> 2 2 A NA 3 NA
#> 3 3 A NA NA 3
#> 4 4 A NA NA 2
您可以这样做,然后将其列绑定到原始数据帧,但您的列将出现无序,并且您将有一个与列A
相同的列A1
。使用select
,可以按正确的顺序选择所需的列。
df %>%
tibble::rowid_to_column() %>%
spread(key = B, value = C) %>%
bind_cols(df) %>%
select(A, B, C, X, Y, Z)
#> A B C X Y Z
#> 1 A X 1 1 NA NA
#> 2 A Y 3 NA 3 NA
#> 3 A Z 3 NA NA 3
#> 4 A Z 2 NA NA 2
更好的做法是在列绑定的内部执行spread
操作,然后删除2个无关列。
bind_cols(
df,
df %>% tibble::rowid_to_column() %>% spread(key = B, value = C)
) %>%
select(-rowid, -A1)
#> A B C X Y Z
#> 1 A X 1 1 NA NA
#> 2 A Y 3 NA 3 NA
#> 3 A Z 3 NA NA 3
#> 4 A Z 2 NA NA 2
创建于2018-11-28由reprex包(v0.2.1(
我们可以使用dcast
从data.table
将'column'C'转换为'wide',然后使用原始数据集转换cbind
library(data.table)
cbind(df1, dcast(setDT(df1), seq_len(nrow(df1))~ B,
value.var = 'C')[, -1, with = FALSE])
# A B C X Y Z
#1: A X 1 1 NA NA
#2: A Y 3 NA 3 NA
#3: A Z 3 NA NA 3
#4: A Z 2 NA NA 2
数据
df1 <- structure(list(A = c("A", "A", "A", "A"), B = c("X", "Y", "Z",
"Z"), C = c(1L, 3L, 3L, 2L)), class = "data.frame", row.names = c(NA,
-4L))