【问题标题】:Collapse data.table column values while grouping分组时折叠 data.table 列值
【发布时间】:2013-04-09 17:13:29
【问题描述】:

给定一个data.table 对象,我会将一些分组列的值折叠到一个对象中,并将生成的对象插入到一个新列中。

dt <- data.table(
            c('A|A', 'B|A', 'A|A', 'B|A', 'A|B'),
            c(0, 0, 1, 1, 0),
            c(22.7, 1.2, 0.3, 0.4, 0.0)
)
setnames(dt, names(dt), c('GROUPING', 'NAME', 'VALUE'))
dt
#    GROUPING NAME VALUE
# 1:      A|A    0  22.7
# 2:      B|A    0   1.2
# 3:      A|A    1   0.3
# 4:      B|A    1   0.4
# 5:      A|B    0   0.0

我认为首先需要指定要分组的列,所以我应该从 dt[, OBJECTS := &lt;expr&gt;, by = GROUPING] 之类的内容开始。

很遗憾,我不知道要使用表达式&lt;expr&gt;,所以结果如下:

#    GROUPING   OBJECTS
# 1:      A|A  <vector>
# 2:      B|A  <vector>
# 3:      A|B  <vector>

每个&lt;vector&gt;必须包含其他列的值。例如,第一个 &lt;vector&gt; 必须是一个命名向量,相当于:

eg <- c(22.7, 0.3)
names(eg) <- c('0', '1')
#    0    1 
# 22.7  0.3

【问题讨论】:

  • 您是否正在尝试将 data.table 重塑为宽格式?
  • 你的expr 应该类似于list(list(...))
  • 但是为什么呢?你不觉得这很难处理吗?为什么不对其进行整形,让列的值对应于0 和1?
  • @Arun 我知道这很难使用,但这正是我需要的 :)

标签: r grouping data.table


【解决方案1】:

在j 内部工作:如果您想让列的值成为向量,则需要将输出包装在list(.) 中。

j 本身需要调用list,因此您的最终表达式将类似于嵌套的list,例如:

dt[, list(allNames=list(NAME), allValues=list(VALUE)), by=GROUPING]

#    GROUPING allNames allValues
# 1:      A|A      0,1  22.7,0.3
# 2:      B|A      0,1   1.2,0.4
# 3:      A|B        0         0

正如@Mnel 指出的那样,等效地:

dt[, lapply(.SD, list), by=GROUPING]

如果您想要长格式,那么您的&lt;expr&gt; 的结构将是:
list( c( list(), list(), ..., list() ) ) 例如:

dt[, list(c(list(NAME), list(VALUE))), by=GROUPING]

#    GROUPING       V1
# 1:      A|A      0,1
# 2:      A|A 22.7,0.3
# 3:      B|A      0,1
# 4:      B|A  1.2,0.4
# 5:      A|B        0
# 6:      A|B        0

或者等价的:

dt[, list(lapply(.SD, c)), by=GROUPING]

【讨论】:

    【解决方案2】:

    我认为这就是你要找的东西:

    dt1 <- dt[, list(list(setNames(VALUE, NAME))), by = GROUPING]
    dt1
    #    GROUPING       V1
    # 1:      A|A 22.7,0.3
    # 2:      B|A  1.2,0.4
    # 3:      A|B        0
    str(dt1)
    # Classes ‘data.table’ and 'data.frame':  3 obs. of  2 variables:
    # $ GROUPING: chr  "A|A" "B|A" "A|B"
    # $ V1      :List of 3
    #  ..$ : Named num  22.7 0.3
    #  .. ..- attr(*, "names")= chr  "0" "1"
    #  ..$ : Named num  1.2 0.4
    #  .. ..- attr(*, "names")= chr  "0" "1"
    #  ..$ : Named num 0
    #  .. ..- attr(*, "names")= chr "0"
    # - attr(*, ".internal.selfref")=<externalptr> 
    dt1$V1
    # [[1]]
    #    0    1 
    # 22.7  0.3 
    # 
    # [[2]]
    #   0   1 
    # 1.2 0.4 
    # 
    # [[3]]
    # 0 
    # 0 
    

    正如@Arun 在 cmets 中指出的那样,在这种情况下,setNames 的“data.table”替代品是setattr(VALUE, 'names', NAME),这是另一种解决方案:

    dt1 <- dt[, list(list(setattr(VALUE, 'names', NAME))), by = GROUPING]
    

    【讨论】:

    • 我认为你应该使用setnames,而不是setNames。
    • @Arun,你能告诉我怎么做吗?没有旧名称,所以不知道该怎么做,所以我只使用了 base R 中的setNames。
    • 阿南达,哦,我明白了。在这种情况下,最好使用setattr(VALUE, 'names', NAME)
    • @Arun, Ananda, setnames(VALUE,NAME) is 比setattr(VALUE, 'names', NAME) 稍微好一点,因为setnames 检查名称的类型和长度是否正确。 old 参数具有双重用途,请参阅 ?setnames。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-08-20
    • 1970-01-01
    • 1970-01-01
    • 2018-12-24
    • 2014-08-04
    • 2017-01-24
    • 2020-04-20
    相关资源
    最近更新 更多