首页 文章

返回向量的data.table聚合,例如scale()

提问于
浏览
4

我最近使用了更大的数据集,并开始学习和迁移到data.table以提高聚合/分组的性能 . 我无法按预期将某些表达式或函数分组 . 以下是我遇到问题的基本操作示例 .

library(data.table)
category <- rep(1:10, 10)
value <- rnorm(100)
df <- data.frame(category, value)
dt <- data.table(df)

如果我想简单地按类别计算每个组的平均值 . 这很容易 .

dt[,mean(value),by="category"]

    category          V1
 1:        1 -0.67555478
 2:        2 -0.50438413
 3:        3  0.29093723
 4:        4 -0.41684790
 5:        5  0.33921764
 6:        6  0.01970997
 7:        7 -0.23684245
 8:        8 -0.04280998
 9:        9  0.01838804
10:       10  0.44295978

如果我尝试使用scale函数或者甚至是从其自身减去值的简单表达式,我会遇到问题 . 忽略分组,我将函数/表达式应用于每一行 . 以下内容按类别返回所有100行而不是10组 .

dt[,scale(value),by="category"]


dt[,value-mean(value),by="category"]

我认为重新创建比例作为返回数字向量而不是矩阵的函数可能有所帮助 .

zScore <- function(x) {
  z=(x-mean(x,na.rm=TRUE))/sd(x,na.rm = TRUE)
  return(z) 
}

dt[,zScore(value),by="category"]

  category          V1
  1:        1 -1.45114132
  2:        1 -0.35304528
  3:        1 -0.94075418
  4:        1  1.44454416
  5:        1  1.39448268
  6:        1  0.55366652
  ....
 97:       10 -0.43190602
 98:       10 -0.25409244
 99:       10  0.35496694
100:       10  0.57323480
     category          V1

这也会返回应用于所有行(N = 100)并忽略分组的zScore函数 . 在使用mean()时,为了使scale()或自定义函数像上面那样使用分组,我缺少什么?

2 回答

  • 2

    你已在评论中澄清了你想要的相同行为:

    ddply(df,"category",transform, zscorebycategory=zScore(value))
    

    这使:

    category       value zscorebycategory
    1          1  0.28860691       0.31565682
    2          1  1.17473759       1.33282374
    3          1  0.06395503       0.05778463
    4          1  1.37825487       1.56643607
    etc
    

    您提供的数据表选项给出:

    category          V1
      1:        1  0.31565682
      2:        1  1.33282374
      3:        1  0.05778463
      4:        1  1.56643607
      etc
    

    这是完全相同的数据 . 但是,您还希望在结果中重复 value 列,并使用更具描述性的内容重命名 V1 变量 . data.table为您提供结果中的分组变量,以及您提供的表达式的结果 . 所以我们修改它来给你想要的行:

    您的

    dt[,zScore(value),by="category"]
    

    变为:

    dt[,list(value=value, zscorebycategory=zScore(value)),by="category"]
    

    列表中的命名项成为结果中的列的位置 .

    plyr = data.table(ddply(df,"category",transform, zscorebycategory=zScore(value)))
    dt   = dt[,list(value=value, zscorebycategory=zScore(value)),by="category"]
    identical(plyr, dt)
    > TRUE
    

    (注意我将你的ddply data.frame结果转换为data.table,以允许 identical 命令工作) .

  • 1

    您声称data.table没有分组是错误的:

    library(data.table)
    category <- rep(1:2, each=4)
    value <- c(rep(c(1:2),each=2),rep(c(4,10),each=2))
    dt <- data.table(category, value)
    
       category value
    1:        1     1
    2:        1     1
    3:        1     2
    4:        1     2
    5:        2     4
    6:        2     4
    7:        2    10
    8:        2    10
    
    dt[,value-mean(value),by=category]
       category   V1
    1:        1 -0.5
    2:        1 -0.5
    3:        1  0.5
    4:        1  0.5
    5:        2 -3.0
    6:        2 -3.0
    7:        2  3.0
    8:        2  3.0
    

    如果要缩放/转换,这正是您想要的行为,因为这些操作按定义返回与输入大小相同的对象 .

相关问题