r语言 - 如何重塑使用id变量作为最终值,当id有重复

  • 本文关键字:id r语言 何重塑 变量 r reshape
  • 更新时间 :
  • 英文 :


我在r中做了很多努力,我的数据看起来是这样的(真实数据有超过12万个观察值):

df <- data.frame(
Input = c(1,2,3,4,4,5,1,3,4),
Output = c(91,91,91,91,91,91,92,92,92)
)
df
Input Output
1     1     91
2     2     91
3     3     91
4     4     91
5     4     91
6     5     91
7     1     92
8     3     92
9     4     92

数字是物理物质的代码。这里的关键是产品91使用了5个输入,而产品92只使用了3个输入,并且91中有重复的(两个4s)

我希望数据帧的输出作为列名,输入作为值(不考虑重复项):

91         92
1          1
2          NA
3          3
4          4
5          NA

所以我用

从长到宽进行了重塑
df2 <- reshape(df, idvar = "Input", v.names = "Output", timevar = "Output", direction = "wide", sep = "_")

这需要花费很多时间,而且我还没能让这篇文章中的其他代码正常工作。它产生一个中间步骤:

Input Output_91 Output_92
1     1        91        92
2     2        91        NA
3     3        91        92
4     4        91        92
5     5        91        NA

然后,我所要做的就是用第一列替换每个Output列,除了NA。我可以简单地一次处理一列。例如:

df2$Output_92[!is.na(df2$Output_92)] <- df2$Input[!is.na(df2$Output_92)]

我一直在尝试对列进行循环,以迭代所有2+列,模仿上面的命令。比如:

for(i in colnames(df2)){
df2[!is.na(i)][i] <- df2$Input[!is.na(i)][i]
}

这行不通。

所以,原则上我只需要在这个循环(问题的标题)中帮助。但建议优化重塑,或者也许是一个更简单的方法来做整个事情更受欢迎。

我意识到副本是我问题的关键,因为没有这些,链接后的标准解决方案工作得很好。相应更新了问题。下面的答案有助于处理ID有重复项的情况。

如果给定的输出有重复的输入,那么假设您不关心计数或以任何不同的方式对待它们,那么下面的所有方法都通过将df替换为unique(df)来工作。(如果需要,也可以使用dplyr::distinct)

一旦你解决了唯一性,那么…这是"只是"。从长到宽重塑/旋转。

基地R

stats::reshape有点难处理,它需要一些不是唯一存在的东西。例如,它要求idvarv.names变量是唯一的列(所以我们复制Input):

df$Input2 <- df$Input
out <- reshape(unique(df), idvar = "Input", v.names = "Input2", timevar = "Output", direction = "wide")
out
#   Input Input2.91 Input2.92
# 1     1         1         1
# 2     2         2        NA
# 3     3         3         3
# 4     4         4         4
# 6     5         5        NA
names(out) <- gsub("Input2\.", "", names(out))
# out[,-1]
91 92
# 1  1  1
# 2  2 NA
# 3  3  3
# 4  4  4
# 6  5 NA

tidyr

(重复列也一样)

library(dplyr)
library(tidyr) # pivot_wider
df %>%
distinct() %>%
mutate(Input2 = Input) %>%
pivot_wider(Input, names_from = "Output", values_from = "Input2") %>%
select(-Input)
# # A tibble: 5 x 2
#    `91`  `92`
#   <dbl> <dbl>
# 1     1     1
# 2     2    NA
# 3     3     3
# 4     4     4
# 5     5    NA

data.table

此处不需要"Input2"

library(data.table)
dcast(unique(as.data.table(df)), Input ~ Output, value.var = "Input")[,-1]
#       91    92
#    <num> <num>
# 1:     1     1
# 2:     2    NA
# 3:     3     3
# 4:     4     4
# 5:     5    NA

这里,unique可以放在as.data.table(.)的内部或外部,由你选择。

简单地说,因为我对重复不感兴趣,我只需要事先删除它们,之后这篇文章中的代码工作得很好。

删除df <- df[!duplicated(df[c("Output","Input")]),]