为什么 melt 在将列表传递给 measure.vars 时会产生警告?

Why does melt produce a warning when one passes a list to measure.vars?

我只是想知道为什么当我将定义的列表传递给 measure.vars arg 时 melt 会抛出此警告?


ny = 3
times = 1990L + 10 * (seq_len(ny)-1)
measure_vars_long = c('gdppc', 'lifexp')
measure_vars_wide = list(measure_var1 = paste0('gdppc_', times[-3]),
                         measure_var2 = paste0('lifexp_', times))


DT = data.table::data.table(
    country = c("c1", "c2", "c3"),
    gdppc_1990 = c(121782.304323278, 126794.359297492, 150476.795178838),
    gdppc_2000 = c(118858.692678623, 143942.932505161, 166981.9295872),
    lifexp_1990 = c(54.4529938697815, 93.5958937462419, 92.9653832130134),
    lifexp_2000 = c(88.843795270659, 77.9958764929324, 96.4652526797727),
    lifexp_2010 = c(81.6346854623407, 90.6221343390644, 63.0786676099524)
)

melt(DT,
     idvars = 'country',
     measure = measure_vars_wide, #with(measure_vars_wide, list(measure_var1, measure_var2))
     variable.name = 'year',
     value.name = c('gdppc', 'lifexp'))

  country year measure_var1 measure_var2
1:      c1    1     121782.3     54.45299
2:      c2    1     126794.4     93.59589
3:      c3    1     150476.8     92.96538
4:      c1    2     118858.7     88.84380
5:      c2    2     143942.9     77.99588
6:      c3    2     166981.9     96.46525
7:      c1    3           NA     81.63469
8:      c2    3           NA     90.62213
9:      c3    3           NA     63.07867
警告信息: 'value.name' 在 'measure.vars' 和 'value.name argument' 中提供; 'measure.vars' 中提供的值优先。

但是,这有效:

melt(DT,
     idvars = 'country',
     measure = with(measure_vars_wide, list(measure_var1, measure_var2)),
     variable.name = 'year',
     value.name = c('gdppc', 'lifexp'))

  country year    gdppc   lifexp
1:      c1    1 121782.3 54.45299
2:      c2    1 126794.4 93.59589
3:      c3    1 150476.8 92.96538
4:      c1    2 118858.7 88.84380
5:      c2    2 143942.9 77.99588
6:      c3    2 166981.9 96.46525
7:      c1    3       NA 81.63469
8:      c2    3       NA 90.62213
9:      c3    3       NA 63.07867

阅读?data.table::melt,我们看到

measure.vars: Measure variables for 'melt'ing. Can be missing, vector,
          list, or pattern-based.
    ...
          For convenience/clarity in the case of multiple 'melt'ed
          columns, resulting column names can be supplied as names to
          the elements 'measure.vars' (in the 'list' and 'patterns'
          usages). See also 'Examples'.

value.name: name for the molten data values column(s). ...
                                            ... though note well that
          the names provided in 'measure.vars' take precedence.

这意味着 measure.vars 中的名称可以用来代替 value.name

为了确认这一点,我们可以使用命名列表变体并删除 value.name 并查看新列名确实来自 names(measure_vars_wide):

melt(DT,
     idvars = 'country',
     measure = measure_vars_wide,
     variable.name = 'year')
#    country   year measure_var1 measure_var2
#     <char> <fctr>        <num>        <num>
# 1:      c1      1     121782.3     54.45299
# 2:      c2      1     126794.4     93.59589
# 3:      c3      1     150476.8     92.96538
# 4:      c1      2     118858.7     88.84380
# 5:      c2      2     143942.9     77.99588
# 6:      c3      2     166981.9     96.46525
# 7:      c1      3           NA     81.63469
# 8:      c2      3           NA     90.62213
# 9:      c3      3           NA     63.07867

所以你可以使用命名列表独占,使用 'gdppc''lifexp' 作为列表的名称,并删除 value.name= 参数,并且在没有任何 warnings.

为什么它在您的第二个代码中表现不同?因为您的 with(., list(.)) 正在返回一个未命名的列表:

with(measure_vars_wide, list(measure_var1, measure_var2))
# [[1]]
# [1] "gdppc_1990" "gdppc_2000"
# [[2]]
# [1] "lifexp_1990" "lifexp_2000" "lifexp_2010"

最后,我认为您可以坚持使用 with(...) 代码,或者将您的代码更改为:

measure_vars_wide = list(gdppc = paste0('gdppc_', times[-3]),
                         lifexp = paste0('lifexp_', times))

melt(DT,
     idvars = 'country',
     measure = measure_vars_wide,
     variable.name = 'year')
#    country   year    gdppc   lifexp
#     <char> <fctr>    <num>    <num>
# 1:      c1      1 121782.3 54.45299
# 2:      c2      1 126794.4 93.59589
# 3:      c3      1 150476.8 92.96538
# 4:      c1      2 118858.7 88.84380
# 5:      c2      2 143942.9 77.99588
# 6:      c3      2 166981.9 96.46525
# 7:      c1      3       NA 81.63469
# 8:      c2      3       NA 90.62213
# 9:      c3      3       NA 63.07867