【问题标题】:Assign intervals / bins by group in data.table在 data.table 中按组分配间隔/箱
【发布时间】:2019-05-06 22:10:10
【问题描述】:

我想按组应用一个函数,该函数根据该组中的值将观察所属的区间分配给一个新变量。我觉得下面的代码应该可以工作,但它似乎使用了整个数据集,而不是组的最大值和最小值。我错过了什么?

#require(data.table)
#fake data
set.seed(12345)
df1 <- data.frame(id_f=c(rep("a a",100),rep("b b",100),rep("c c",100)), 
                   L=c(abs(rnorm(100,50,20)),abs(rnorm(100,90,20)),abs(rnorm(100,220,20))), 
                   w=abs(rnorm(300,6,3))) 
dt2 = as.data.table(df1)

#the offending data.table function
dt2[,"bins":= findInterval(L, c((max(L)-min(L))/10*c(1:9)),left.open=T)+1, by=id_f]

编辑:

在“a a”列中,“a a”范围内将有 10 个等间距的 bin,并且将为每个原始观测值分配一个 bin 编号,因为真实数据有 6,000 个观测值,每个观测值都有多个成员斌。所以输出会是这样的:(为简洁起见,这是一个三间隔的例子)

id_f  L    w     bins
a a   1    1.0   1
a a   2    1.1   2
a a   3    5.0   3
b b   3    2.0   1
b b   6    3.5   2
b b   9    7.0   3
c c   10   1.0   1
c c   15   1.5   2
c c   20   6.0   3

我原以为我对findInterval 的调用会完成此操作,但显然它从全球数据集中获取minmax,而不仅仅是从组中获取。如何让它从组中获取minmax,然后使用它来计算用于该组的间隔?

【问题讨论】:

  • cut() 是执行此操作的内置函数,将其传递给显式的 breaks 参数。当您使用随机数据时,也请使用set.seed(),以使我们其他人可以重现这一点。经过多次编辑后,这个问题仍然无法重现,啊。
  • 将来会设置.seed。谢谢。

标签: r data.table intervals


【解决方案1】:

我认为通过指定我们想要的breaks 的数量在这里使用cut 会容易得多

library(data.table)
setDT(dt2)[,"bins":= cut(L, breaks = 10, labels = 1:10), by=id_f]

dt2
#     id_f     L     w bins
#  1:  a a  71.5  2.96    8
#  2:  a a  49.5  3.63    5
#  3:  a a  49.3  6.90    5
#  4:  a a  19.7 10.92    2
#  5:  a a  65.8  9.25    7
# ---                      
#296:  c c 206.0  6.50    4
#297:  c c 224.8  4.04    6
#298:  c c 213.0 10.36    5
#299:  c c 227.4  3.58    6
#300:  c c 224.9  7.12    6

我们也可以在 dplyr 或 base R 中执行此操作

library(dplyr)

dt2 %>%
  group_by(id_f) %>%
  mutate(bins = cut(L, breaks = 10, labels = 1:10))

with(dt2, ave(L, id_f, FUN = function(x) cut(x, breaks = 10, labels = 1:10)))

【讨论】:

  • 是的! cut 正是我想要的。谢谢!
【解决方案2】:

您需要运行表格函数来演示该问题。 by-操作似乎正在“工作”

    > dt2[ , list(mn=min(L), mx=max(L) ), by=id_f]
   id_f         mn       mx
1:  a a   5.462025 104.2456
2:  b b  43.824476 138.4843
3:  c c 168.075002 276.5598
> dt2[ , table(id_f, bins)]
     bins
id_f    1   2   3   4   5   6   7   8   9  10
  a a   3   5  10  10  19  13  21  10   4   5
  b b   0   0   0   0   1   3  10   8  19  59
  c c   0   0   0   0   0   0   0   0   0 100

显然你的结果会有所不同,因为你没有使用set.seed()

png(); par(mfrow=c(3,1)); tapply(df1$L, df1$id_f, hist); dev.off()

【讨论】:

  • 感谢您的回复。生成数据的代码完全按照它应该的方式工作。我认为,问题在于 min() 和 max() 来自全局 data.table,而不是“by=id_f”中的分组变量指示的子集。请参阅已编辑的问题。
猜你喜欢
  • 2016-10-06
  • 2016-06-13
  • 2012-07-25
  • 1970-01-01
  • 2010-09-16
  • 1970-01-01
  • 2022-10-23
  • 2011-12-20
相关资源
最近更新 更多