使用 data.table 中列的值对 long-data.table 进行子集化并转换其他值

new*_*r_7 3 r subset data.table dcast

我有一个 2200 万个观察行的数据表,其形式如下:

`dt <- data.table(
  firm_id = c(1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2),
  metric = c("AN_BILANT", "OPEX", "CAPEX","AN_BILANT","OPEX", "CAPEX", "AN_BILANT", "OPEX", "CAPEX", "AN_BILANT","OPEX", "CAPEX"),
  value = c(2013, 10, 3,2014, 11, 5, 2007, 25, 10, 2009, 23, 7)
)`
Run Code Online (Sandbox Code Playgroud)

我想使用 data.table 生成以下输出

`output_dt <- data.table(
  firm_id = c(1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2),
  metric = c("OPEX", "CAPEX","OPEX", "CAPEX", "OPEX", "CAPEX", "OPEX", "CAPEX"),
AN_BILANT = c(2013, 2013, 2014, 2014, 2007, 2007, 2009) 
  value = c( 10, 3,11, 5, 25, 10,23, 7)
)
`
Run Code Online (Sandbox Code Playgroud)

我最初尝试了以下方法:

dcast(dt[metric == "AN_BILANT"], firm_id ~ metric, value.var = "value", fun.aggregate = function(x) x)

但我收到以下错误

错误:聚合函数应采用向量输入并返回单个值(长度=1)。然而,函数返回 length!=1。该值必须用于填充任何缺失的组合,因此长度必须=1。通过显式设置“fill”参数来覆盖,或者修改您的函数以适当地处理这种情况。

我也尝试过

dcast.data.table(dt[, N:=1:.N, metric], firm_id~metric, subset = (metric=="AN_BILANT") ) 我在这里收到警告

缺少聚合函数,默认为“length”

r2e*_*ans 5

我喜欢 akrun 的方法,但如果数据迫使您选择替代方案(以防cumsum对数据排序过于敏感),您可以尝试如下所示的 dcast/melt 方法。请注意,由于firm_id不只包含每个变量之一metric,因此我们需要临时添加另一个变量,以便在初始过程中不会过度减少dcast

library(data.table)
dcast(DT[, grp := seq_len(.N), by = .(firm_id, metric)],
      firm_id + grp ~ metric, value.var = "value")[, grp := NULL] |>
  melt(c("firm_id", "AN_BILANT"), variable.name = "metric")
#    firm_id AN_BILANT metric value
#      <num>     <num> <fctr> <num>
# 1:       1      2013  CAPEX     3
# 2:       1      2014  CAPEX     5
# 3:       2      2007  CAPEX    10
# 4:       2      2009  CAPEX     7
# 5:       1      2013   OPEX    10
# 6:       1      2014   OPEX    11
# 7:       2      2007   OPEX    25
# 8:       2      2009   OPEX    23
Run Code Online (Sandbox Code Playgroud)

当然,行的顺序不相同,但双重重塑通常不能保证这一点。

  • 只是 curions,为什么不使用 data.tables 固有的 `[` 函数而不是本机管道?即 `, grp := NULL ][,melt(.SD, c("firm_id", "AN_BILANT"), variable.name = "metric")]`? (2认同)