【问题标题】:factor levels order modified after aggregation with data.table与 data.table 聚合后修改的因子级别顺序
【发布时间】:2014-02-11 23:13:10
【问题描述】:

我正在使用以下函数,grp 与data.table 聚合并遇到问题。

问题是因子变量fc_x 的级别顺序在聚合后没有保持相同的顺序。 是我的功能有问题,还是这个“正常”意味着它有解释?

grp <- function(x) {
  percentage = as.numeric(table(x)/length(x))
  list(x = factor(levels(x)),
       percentage = percentage,
       label = paste0( round( as.numeric(table(x)/length(x), 0 ) * 100 ), "%")
  )
}

set.seed(123)
DT <- data.table(x = rnorm(100, 100, 50), fac = factor(letters[1:10]))
DT$fc_x <- cut(DT$x, breaks = c(0, 50, 100, 10e5), right = T,
            labels = c("0-50", "51-100", "+100"))

str(DT)
# Classes ‘data.table’ and 'data.frame':  100 obs. of  3 variables:
# $ x   : num  90.7 59.4 18 125.4 187.7 ...
# $ fac : Factor w/ 10 levels "a","b","c","d",..: 1 2 3 4 5 6 7 8 9 10 ...
# $ fc_x: Factor w/ 3 levels "0-50","51-100",..: 2 2 1 3 3 3 3 3 1 1 ...

levels(DT$fc_x)
# [1] "0-50"   "51-100" "+100"

AGG <- DT[, grp(fc_x), by=fac]

levels(AGG$x)
# [1] "+100"   "0-50"   "51-100"

编辑

将“+100”更改为“1000”提供了类似的结果

DT <- data.table(x = rnorm(100, 100, 50), fac = factor(letters[1:10]))
DT$fc_x <- cut(DT$x, breaks = c(0, 50, 100, 10e5), right = T,
               labels = c("0-50", "51-100", "1000"))

levels(DT$fc_x)
# [1] "0-50"   "51-100" "1000"

AGG <- DT[, grp(fc_x), by=fac]
levels(AGG$x)
# [1] "0-50"   "1000"   "51-100"

在 cut() 语句中使用 ordered = TRUE 提供相同的结果

DT <- data.table(x = rnorm(100, 100, 50), fac = factor(letters[1:10]))
DT$fc_x <- cut(DT$x, breaks = c(0, 50, 100, 10e5), right = T, ordered = T,
               labels = c("0-50", "51-100", "1000"))

levels(DT$fc_x)
# [1] "0-50"   "51-100" "1000"

AGG <- DT[, grp(fc_x), by=fac]
levels(AGG$x)
# [1] "0-50"   "1000"   "51-100"

【问题讨论】:

  • 1.我认为您的意思是 right=Tcut 声明中。 2. 第三种可能是无意的,也就是错误。
  • 1.当然。我已经修改了它,仍然得到相同的结果。
  • 对,我并不是说这是问题所在,只是您在代码中有错字(这可能会改变某个数字所属的类别,但不会改变问题)。
  • 对不起,也许这看起来很粗鲁。无意!

标签: r data.table aggregation


【解决方案1】:

我认为问题在于,当您在函数中定义 x 时,您没有提供标签,因此它只是将因子级别按字母顺序排列,所以我认为您只需将标签添加到您的函数中。

DT$fc_x <- cut(DT$x, breaks = c(0, 50, 100, 10e5), rigth = T, 
labels = c("0-50", "51-100",  "+100"))

factor(levels(DT$fc_x))
[1] 0-50   51-100 +100  
Levels: 0-50 +100 51-100

factor(levels(DT$fc_x),  labels = c("0-50", "51-100", "100+"))
[1] 0-50   +100   51-100
Levels: 0-50 51-100 +100


grp <- function(x) {
  percentage = as.numeric(table(x)/length(x))
  list(
       x = factor(levels(x), labels = levels(x)),
       percentage = percentage,
       label = paste0( round( as.numeric(table(x)/length(x), 0 ) * 100 ), "%")
  )
}

DT <- data.table(x = rnorm(100, 100, 50), fac = factor(letters[1:10]))

DT$fc_x <- cut(DT$x, breaks = c(0, 50, 100, 10e5), rigth = T,
               labels = c("0-50", "51-100", "+100"))
AGG <- DT[, grp(fc_x), by=fac]
levels(AGG$x)
[1] "0-50"   "51-100" "100+"  

【讨论】:

  • 对不起我之前的评论,这是不正确的。问题确实是grp 中的因子创建。
  • 你不是在grp函数中硬编码关卡吗?
  • 使用你的方法,我应该在每次使用 cut 时编写一个函数。这不是一个非常实用的解决方案...
  • 您的问题是“我的功能是否有问题,或者这是否“正常”意味着它有解释?”。我在说明这是您的函数的问题,而不是 data.table 的问题。
  • 尽管这不是您最初要求的,我已经更新了 grp 函数以使用您提供的因子水平的顺序。
【解决方案2】:

将修改后的 grp 函数版本用于真实数据集后,级别很好,但与聚合后的实际值不匹配。

我想出了这个,我相信将名称传递给表格结果的更简单的解决方案。 如果我不使用 as.numeric(table(...)) 我保留名称。

感谢马特的帮助,马修。我会接受你的回答,因为它很有帮助。

grp <- function(x) {
  percentage = data.frame(table(x)/length(x))
  list(x = factor(percentage[[1]]),
       percentage = percentage[[2]],
       label = paste0( round( as.numeric(percentage[[2]], 2 ) * 100 ) , "%")
  )
}

【讨论】:

    猜你喜欢
    • 2013-01-16
    • 1970-01-01
    • 1970-01-01
    • 2021-06-26
    • 2021-12-13
    • 2018-09-09
    • 1970-01-01
    • 2021-08-29
    • 1970-01-01
    相关资源
    最近更新 更多