【问题标题】:Reshape multiple values at once一次重塑多个值
【发布时间】:2025-11-24 09:40:01
【问题描述】:

我有一个很长的数据集我想扩大,我很好奇是否有一种方法可以使用 R 中的 reshape2 或 tidyr 包一步完成。

数据框df如下所示:

id  type    transactions    amount
20  income       20          100
20  expense      25          95
30  income       50          300
30  expense      45          250

我想解决这个问题:

id  income_transactions expense_transactions    income_amount   expense_amount
20       20                           25                 100             95
30       50                           45                 300             250

我知道我可以通过例如 reshape2 获得其中的一部分:

dcast(df, id ~  type, value.var="transactions")

但是有没有办法一次性重塑整个 df,同时解决“交易”和“金额”变量?最好使用新的更合适的列名?

【问题讨论】:

    标签: r dataframe reshape reshape2 tidyr


    【解决方案1】:

    在“reshape2”中,您可以使用recast(尽管根据我的经验,这不是一个广为人知的功能)。

    library(reshape2)
    recast(mydf, id ~ variable + type, id.var = c("id", "type"))
    #   id transactions_expense transactions_income amount_expense amount_income
    # 1 20                   25                  20             95           100
    # 2 30                   45                  50            250           300
    

    你也可以使用base R的reshape

    reshape(mydf, direction = "wide", idvar = "id", timevar = "type")
    #   id transactions.income amount.income transactions.expense amount.expense
    # 1 20                  20           100                   25             95
    # 3 30                  50           300                   45            250
    

    或者,你可以meltdcast,像这样(这里是“data.table”):

    library(data.table)
    library(reshape2)
    dcast.data.table(melt(as.data.table(mydf), id.vars = c("id", "type")), 
                     id ~ variable + type, value.var = "value")
    #    id transactions_expense transactions_income amount_expense amount_income
    # 1: 20                   25                  20             95           100
    # 2: 30                   45                  50            250           300
    

    在更高版本的dcast.data.table 中来自“data.table”(1.9.8) you will be able to do this directly。如果我理解正确,@Arun 试图实现的将是进行重塑,而无需首先 melt 数据,这就是 recast 目前发生的情况,它本质上是 melt + @987654333 的包装器@ 操作序列。


    并且,为了彻底起见,这里是tidyr 方法:

    library(dplyr)
    library(tidyr)
    mydf %>% 
      gather(var, val, transactions:amount) %>% 
      unite(var2, type, var) %>% 
      spread(var2, val)
    #   id expense_amount expense_transactions income_amount income_transactions
    # 1 20             95                   25           100                  20
    # 2 30            250                   45           300                  50
    

    【讨论】:

    • 这是一个不错的答案(开明+不错的答案徽章正在路上...),但不确定我们需要什么tidyrdplyrdata.table,@ 987654339@ 等,当有这样一种简单的方法可以用基础 R 完成它时
    • @DavidArenburg,规模化速度,真的。我是reshape 的老铁杆粉丝,但如果有人正在处理远程大数据,这不是我的第一个建议。
    • reshape() 简单吗?我要说的就是“bahahahaha”
    • @hadley,我不能代表 David,但我没有将他的评论解释为意味着 reshape() 很简单,而是暗示这里的 reshape() 方法实际上相当简单.
    • 在这种情况下,与 tidyr、dplyr、data.table、reshape2 等“混淆”的全部意义在于它们可以更好地泛化到新问题,而 reshape() 没有。跨度>
    【解决方案2】:

    使用 data.table v1.9.6+,我们可以同时转换多个value.var 列(并且还可以在fun.aggregate 中使用多个聚合函数)。请参阅?dcast 了解更多信息以及示例部分。

    require(data.table) # v1.9.6+
    dcast(dt, id ~ type, value.var=names(dt)[3:4])
    #    id transactions_expense transactions_income amount_expense amount_income
    # 1: 20                   25                  20             95           100
    # 2: 30                   45                  50            250           300
    

    【讨论】:

      最近更新 更多