我尝试使用融合公式将数据框从宽格式转换为长格式。挑战在于我有多个标记相同的列名。当我使用熔化函数时,它会从重复列中删除值。我已经阅读了类似的问题,建议使用重塑功能,但我无法使其工作。
要重现我的起始数据框:
conversion.id<-c("1", "2", "3")
interaction.num<-c("1","1","1")
interaction.num2<-c("2","2","2")
conversion.id<-as.data.frame(conversion.id)
interaction.num<-as.data.frame(interaction.num)
interaction.num2<-as.data.frame(interaction.num2)
conversion<-c(rep("1",3))
conversion<-as.data.frame(conversion)
df<-cbind(conversion.id,interaction.num, interaction.num2, conversion)
names(df)[3]<-"interaction.num"
数据框如下所示:
当我运行以下融化功能时:
melt.df<-melt(df,id="conversion.id")
它删除了interaction.num == 2列,看起来像这样:
我想要的数据框如下:
我看到了以下文章,但我对重塑功能并不太熟悉,也无法让它发挥作用。
How to reshape a dataframe with "reoccurring" columns?
为了增加一层复杂性,我正在寻找一种有效的方法。我需要在大约1M行的数据帧上执行此操作,其中许多列标记为相同。
非常感谢任何建议!
答案 0 :(得分:3)
以下是使用tidyr
代替reshape2
的解决方案。其中一个优点是gather_
函数,它将字符向量作为输入。所以,首先我们可以替换所有有问题的&#34;具有唯一名称的变量名称(通过在每个名称的末尾添加数字)然后我们可以收集(相当于融化)这些特定变量。变量的唯一名称存储在名为&#34; prob_var_name&#34;的临时变量中,我最后删除了该变量。
library(tidyr)
library(dplyr)
var_name <- "interaction.num"
problem_var <- df %>%
names %>%
equals(var_name) %>%
which
replaced_names <- mapply(paste0,names(df)[problem_var],seq_along(problem_var))
names(df)[problem_var] <- replaced_names
df %>%
gather_("prob_var_name",var_name,replaced_names) %>%
select(-prob_var_name)
conversion.id conversion interaction.num
1 1 1 1
2 2 1 1
3 3 1 1
4 1 1 2
5 2 1 2
6 3 1 2
由于gather_
的引用功能,您可以将所有这些包装到函数中并将var_name
设置为变量。那么也许你可以在所有重复的变量上使用它?
答案 1 :(得分:3)
这是使用data.table
的解决方案。您只需提供索引而不是名称。
require(data.table)
require(reshape2)
ans <- melt(setDT(df), measure=2:3,
value.name="interaction.num")[, variable := NULL]
# conversion.id conversion interaction.num
# 1: 1 1 1
# 2: 2 1 1
# 3: 3 1 1
# 4: 1 1 2
# 5: 2 1 2
# 6: 3 1 2
您可以通过2:3
获取索引grep("interaction.num", names(df))
。
答案 2 :(得分:1)
以下是基础R中适用于您的方法:
x <- grep("interaction.num", names(df)) ## as suggested by Arun
## Make more friendly names for reshape
names(df)[x] <- paste(names(df)[x], seq_along(x), sep = "_")
## Reshape
reshape(df, direction = "long",
idvar=c("conversion.id", "conversion"),
varying = x, sep = "_")
# conversion.id conversion time interaction.num
# 1.1.1 1 1 1 1
# 2.1.1 2 1 1 1
# 3.1.1 3 1 1 1
# 1.1.2 1 1 2 2
# 2.1.2 2 1 2 2
# 3.1.2 3 1 2 2
另一种可能性是stack
而不是reshape
:
x <- grep("interaction.num", names(df)) ## as suggested by Arun
cbind(df[-x], stack(lapply(df[x], as.character)))
根据您的值实际上是否为数字,可能不需要lapply(df[x], as.character)
。您创建此示例数据的方式是factor
s。