我在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
有点难处理,它需要一些不是唯一存在的东西。例如,它要求idvar
和v.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")]),]