dplyr 使用两个键将数据转换为宽格式

dplyr convert data to wide format with two keys

我有一个如下所示的数据框:

ID, Type, Unit, Value, Status
A, L1, cm, 100, F
A, L2, %, 70, F
A, L3, cm, 100, F
A, L4, %, 80, F
B, L1, cm, 100, T
B, L2, %, 70, T
B, L3, cm, 100, T
B, L4, %, 80, T

我想将其转换为宽格式:

ID, L1(cm), L2(%), L3(cm), L4(%), Status
A, 100, 70, 100, 80, F
B, 100, 70, 100, 80, T

我在dplyr中使用spread函数,key是Type,value是Value。我想我将不得不在 ID 列上再做一次。我想知道是否有标准的方法可以做到这一点,或者是否有更简洁的方法。

我们可以使用tidyverse。使用 'Type' 和 'Unit' 使用 pasteunite (不太灵活)创建一个连接列,然后在删除后使用 spread 到 'wide' 格式不需要的列

library(tidyverse)
df1 %>%
  mutate(TypeUnit = paste0(Type, "(", Unit, ")")) %>%
  select(-Type, -Unit) %>%
  spread(TypeUnit, Value) 
#   ID Status  L1(cm)  L2(%)  L3(cm)  L4(%)
#1  A      F     100     70     100     80
#2  B      T     100     70     100     80

数据

df1 <- structure(list(ID = c("A", "A", "A", "A", "B", "B", "B", "B"), 
Type = c(" L1", " L2", " L3", " L4", " L1", " L2", " L3", 
" L4"), Unit = c("cm", "%", "cm", "%", "cm", "%", "cm", "%"
), Value = c(100L, 70L, 100L, 80L, 100L, 70L, 100L, 80L), 
Status = c(" F", " F", " F", " F", " T", " T", " T", " T"
)), row.names = c(NA, -8L), class = "data.frame")

@akrun 的回答绝对漂亮。 如果您还想尝试 reshape,下面的内容应该也可以,但您之后可能需要重命名列名。

使用相同的数据

df <- data.frame(ID = c("A", "A", "A", "A", "B", "B", "B", "B"), 
             Type = c(" L1", " L2", " L3", " L4", " L1", " L2", " L3", " L4"), 
             Unit = c("cm", "%", "cm", "%", "cm", "%", "cm", "%"), 
             Value = c(100, 70, 100, 80, 100, 70, 100, 80), 
             Status = c(" F", " F", " F", " F", " T", " T", " T", " T"))

使用包 reshape2

library(reshape2)
dcast(df, ID + Status  ~ Type + Unit, value.var = "Value" )

输出

  ID Status  L1_cm  L2_%  L3_cm  L4_%
1  A      F    100    70    100    80
2  B      T    100    70    100    80