如何使用data.table按组对随机变量进行子集筛选?

3

我希望在data.table中,按组获取一个变量的最小值和随机抽样。

data.table(ggplot2::movies)[, list(min=min(rating), random=sample(rating, 1)), by=list(year, Action)]

无法工作:

Error in `[.data.table`(data.table(movies), , list(min(rating), sample(rating,  : 
Column 2 of result for group 88 is type 'integer' but expecting type 'double'. Column types must be consistent for each group.

如果我将其强制转换为数字,我会得到一个惊人的结果:随机评分低于(?!!)相同类别的最小值的类别。
data.table(ggplot2::movies)[, list(min=min(rating), random=as.numeric(sample(rating, 1))), by=list(year, Action)][random<min]
   year Action min random
1: 1916      1 6.2      6
2: 1911      1 5.7      1
3: 1901      1 4.2      3
4: 1914      1 6.1      6
5: 1923      1 8.2      4
6: 1918      1 5.9      5
7: 1921      1 7.5      4

使用.SD不会改变任何东西:

data.table(ggplot2::movies)[, list(min=min(rating), random=as.numeric(sample(.SD$rating, 1))), by=list(year, Action)][random<min]
   year Action min random
1: 1916      1 6.2      2
2: 1911      1 5.7      4
3: 1893      0 7.0      2
4: 1901      1 4.2      4
5: 1914      1 6.1      5
6: 1923      1 8.2      8
7: 1918      1 5.9      4

更糟糕的是,当变量是整数时没有出现错误:

data.table(ggplot2::movies)[, list(min=min(votes), random=sample(votes, 1)), by=list(year, Action)][random<min]
   year Action min random
1: 1916      1 135     43
2: 1911      1  26      2
3: 1893      0  90     52
4: 1901      1  13     12
5: 1923      1 757    368
6: 1918      1  60     49
7: 1921      1  73     48

显然,sample函数不想在子集上工作...
帮帮我!

请提供示例数据。https://dev59.com/eG025IYBdhLWcg3whGSx#28481250 此外,您是否想要提到您从哪个包中获取了“%>%”?magrittr,也许? - Frank
顺便说一下,data.table(iris)[, .(min = min(Sepal.Length), rand = sample(Sepal.Length,1)), by=.(Species)]。我很好奇你是否发现了一个错误,但如果没有示例,我们无法确认它。 - Frank
2
我可以删除%>%并在movies前面添加ggplot2::。我会编辑我的问题。 - Arthur
谢谢。我也对此感到困惑。希望其他人能提供一些见解。 - Frank
2个回答

2
你陷入了标准的“样本”陷阱。从“?sample”中得知:
如果x的长度为1,是数值型(is.numeric)且x >= 1,则通过sample进行抽样,范围是1:x。请注意,当x在调用sample(x)等函数时长度不同时,这种便利功能可能会导致不良行为。
例如,使用“?sample”中的resample建议。

1
@Arthur,你不需要为了重采样而加载gdata。正如eddi所提到的,在?sample文档的示例部分中已经定义了它,即resample <- function(x, ...) x[sample.int(length(x), ...)] - Frank

0

我终于找到了一个解决方法。但它并没有说明为什么在子集上sample()函数不能按预期工作。

data.table(movies)[, list(min=min(votes), random=votes[sample(1:.N, 1)]), by=list(year, Action)]
     year Action min random
  1: 1971      0   5     77
  2: 1939      0   5     13
  3: 1941      0   5      7
  4: 1996      0   5   4066
  5: 1975      0   5      6
 ---                       
201: 1931      1   8      8
202: 1928      1  17     41
203: 1923      1 757    757
204: 1918      1  60     60
205: 1921      1  73     73

这是之前描述的奇怪行为的结尾:

data.table(movies)[, list(min=min(votes), random=votes[sample(1:.N, 1)]), by=list(year, Action)][random<min]
Empty data.table (0 rows) of 4 cols: year,Action,min,random

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接