【问题标题】:Transforming a dataframe by "multiplying" a column's elements by the names of the other columns [duplicate]通过将列的元素与其他列的名称“相乘”来转换数据框[重复]
【发布时间】:2020-03-18 15:31:42
【问题描述】:

下面是一个例子。如何将带有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]) 够用吗?
  • 不需要全部名称。

标签: r dataframe reshape


【解决方案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

【讨论】:

    【解决方案2】:

    代码

    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 所期望的。
    • 嗯,从技术上讲你是对的,但是我怀疑列顺序(xnyn 或 ynxn)在这种特定情况下是否很重要。
    【解决方案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
    

    【讨论】:

      猜你喜欢
      • 2018-12-01
      • 1970-01-01
      • 1970-01-01
      • 2021-02-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多