通过将一列元素乘以其他列的名称,转换数据框架

3
以下是一个示例。如何将具有列名names的数据框df转换为下面的df.transformed形式?
> df <- data.frame("names" = c("y1", "y2"), "x1" = 1:2, "x2" = 4:5)
> df
  names x1 x2
1    y1  1  4
2    y2  2  5


> df.transformed <- data.frame("y1x1" = 1, "y1x2" =4, "y2x1" = 2, "y2x2" = 5)
> df.transformed
  y1x1 y1x2 y2x1 y2x2
1    1    4    2    5

unlist(df[-1]) 足够吗? - Sotos
不需要全部名称。 - its.me.adam
3个回答

4

代码

require(data.table); setDT(df)

dt = melt(df, id.vars = 'names')[, col := paste0(variable, names)]
out = dt$value; names(out) = dt$col

结果

> data.frame(t(out))

x1y1 x1y2 x2y1 x2y2 
   1    2    4    5 

输出结果与 OP 的预期不符。 - slava-kohut
嗯,从技术上讲你是对的,但我怀疑在这种特定情况下列的顺序(xnyn或ynxn)并不重要。 - JDG

3
你可以在基本的R中实现这个功能。这个方法适用于任何数据框的大小。思路是结合Reduceouter构建数据框列名。
df <- data.frame("names" = c("y1", "y2"), "x1" = 1:2, "x2" = 4:5)

df_names <- outer(df[,1], names(df[,-1]), paste0)
df.transformed <- as.data.frame(matrix(,ncol = nrow(df)*ncol(df[,-1]), nrow = 0))
names(df.transformed) <- Reduce(`c`,t(df_names))
df.transformed[1,] <- Reduce(`c`,t(df[-1]))

输出

#  y1x1 y1x2 y2x1 y2x2
#    1    4    2    5

1
你可以使用新的tidyr::pivot_wider在一行中完成此操作。设置多个列作为值意味着名称将被粘贴在一起以进行赋值。
library(tidyr)

pivot_wider(df, names_from = names, values_from = c(x1, x2), names_sep = "")
#> # A tibble: 1 x 4
#>    x1y1  x1y2  x2y1  x2y2
#>   <int> <int> <int> <int>
#> 1     1     2     4     5

然而,列名(“x1”,“x2”)首先出现。如果您需要交换名称中的“x”和“y”组件,则可以使用dplyr :: rename_all进行正则表达式替换。

df %>%
  pivot_wider(names_from = names, values_from = c(x1, x2), names_sep = "") %>%
  dplyr::rename_all(gsub, pattern = "(x\\d+)(y\\d+)", replacement = "\\2\\1")
#> # A tibble: 1 x 4
#>    y1x1  y2x1  y1x2  y2x2
#>   <int> <int> <int> <int>
#> 1     1     2     4     5

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接