gpt4 book ai didi

r - 复杂的汇总功能-是否可以使用R data.table包解决?

转载 作者:行者123 更新时间:2023-12-01 15:43:16 27 4
gpt4 key购买 nike

我正在重新编写一些可分析大量数据(约1700万行)的R脚本,我想我会尝试使用data.table包(我只是在学习!)来提高其内存效率。

代码的一部分让我有些困惑。我无法发布原始解决方案,因为(1)它很糟糕(slow!),并且(2)关于数据而言,它非常细微,只会使这个问题复杂化。

相反,我给出了这个玩具示例(它确实是一个玩具示例):

ds <- data.table(ID=c(1,1,1,1,2,2,2,3,3,3),
Obs=c(1.5,2.5,0.0,1.25,1.45,1.5,2.5,0.0,1.25,1.45),
Pos=c(1,3,5,6,2,3,5,2,3,4))

看起来像这样:
    ID  Obs Pos
1: 1 1.50 1
2: 1 2.50 3
3: 1 0.00 5
4: 1 1.25 6
5: 2 1.45 2
6: 2 1.50 3
7: 2 2.50 5
8: 3 0.00 2
9: 3 1.25 3
10: 3 1.45 4

为了便于说明,我假设我们正在观察火车(每列火车都有自己的 ID ),在线性单向轨道上移动,并观察到有关火车的信息(某些值(value),对问题没有重要意义)沿着轨道在设定位置( pos ,这里从1-6)开始。预计火车不会使其完全覆盖轨道(可能在到达位置6之前就爆炸了),有时观察者会错过观察…位置是连续的(因此,如果我们错过了观察的话)火车在位置4,但是我们在位置5观察到它,我们知道它一定已经通过位置4)。

从上面的data.table,我需要生成一个像这样的表:
   Pos Count
1: 1 3
2: 2 3
3: 3 3
4: 4 3
5: 5 2
6: 6 1

在data.table ds中,对于每个唯一的 Pos ,无论计数是否在该轨道上的该位置进行观测,我都会对到达该轨道上该位置的火车数量进行计数。 。

如果有人对如何解决这个问题有任何想法或建议,将不胜感激。不幸的是,我对data.table不够熟悉,无法知道是否可以这样做!或者它可能是一个非常简单的问题,而且我很慢:)

最佳答案

好问题!!示例数据的构造和解释都非常好。

首先,我将显示此答案,然后将逐步解释它。

> ids = 1:3   # or from the data: unique(ds$ID)
> pos = 1:6 # or from the data: unique(ds$Pos)
> setkey(ds,ID,Pos)

> ds[CJ(ids,pos), roll=-Inf, nomatch=0][, .N, by=Pos]
Pos N
1: 1 3
2: 2 3
3: 3 3
4: 4 3
5: 5 2
6: 6 1
>

这对于大数据也应该非常有效。

逐步

首先,我尝试了Cross Join(CJ);即针对每个位置的每列火车。
> ds[CJ(ids,pos)]
ID Pos Obs
1: 1 1 1.50
2: 1 2 NA
3: 1 3 2.50
4: 1 4 NA
5: 1 5 0.00
6: 1 6 1.25
7: 2 1 NA
8: 2 2 1.45
9: 2 3 1.50
10: 2 4 NA
11: 2 5 2.50
12: 2 6 NA
13: 3 1 NA
14: 3 2 0.00
15: 3 3 1.25
16: 3 4 1.45
17: 3 5 NA
18: 3 6 NA

我看到每列火车有6行。我看到三列火车。如我所料,我有18行。我在未观察到该火车的地方看到了 NA。好。检查一下交叉连接似乎正在工作。现在让我们建立查询。

您写道,如果在位置n观察到火车,那么它必须已经通过了先前的位置。我立即在考虑 roll。让我们尝试一下。
ds[CJ(ids,pos), roll=TRUE]
ID Pos Obs
1: 1 1 1.50
2: 1 2 1.50
3: 1 3 2.50
4: 1 4 2.50
5: 1 5 0.00
6: 1 6 1.25
7: 2 1 NA
8: 2 2 1.45
9: 2 3 1.50
10: 2 4 1.50
11: 2 5 2.50
12: 2 6 2.50
13: 3 1 NA
14: 3 2 0.00
15: 3 3 1.25
16: 3 4 1.45
17: 3 5 1.45
18: 3 6 1.45

嗯这就使每辆火车的观测结果向前滚动。它在位置1为火车2和3保留了一些 NA,但是您说如果在位置2观察到火车,它必须已经通过位置1。它还将对火车2和3的最后观察向前滚动到位置6,但是您说火车可能会爆炸。因此,我们想向后退!那是 roll=-Inf。这是一个复杂的 -Inf,因为您还可以控制向后滚动的距离,但是对于这个问题,我们不需要它;我们只是想无限地向后滚动。让我们尝试 roll=-Inf看看会发生什么。
> ds[CJ(ids,pos), roll=-Inf]
ID Pos Obs
1: 1 1 1.50
2: 1 2 2.50
3: 1 3 2.50
4: 1 4 0.00
5: 1 5 0.00
6: 1 6 1.25
7: 2 1 1.45
8: 2 2 1.45
9: 2 3 1.50
10: 2 4 2.50
11: 2 5 2.50
12: 2 6 NA
13: 3 1 0.00
14: 3 2 0.00
15: 3 3 1.25
16: 3 4 1.45
17: 3 5 NA
18: 3 6 NA

这样更好差不多好了。我们现在要做的就是计数。但是,火车2和3爆炸后,那些讨厌的 NA就在那里了。让我们删除它们。
> ds[CJ(ids,pos), roll=-Inf, nomatch=0]
ID Pos Obs
1: 1 1 1.50
2: 1 2 2.50
3: 1 3 2.50
4: 1 4 0.00
5: 1 5 0.00
6: 1 6 1.25
7: 2 1 1.45
8: 2 2 1.45
9: 2 3 1.50
10: 2 4 2.50
11: 2 5 2.50
12: 3 1 0.00
13: 3 2 0.00
14: 3 3 1.25
15: 3 4 1.45

顺便说一句, data.table尽可能将其包含在一个 DT[...]中,因为这是优化查询的方式。在内部,它不会创建 NA然后将其删除;它永远不会首先创建 NA。这个概念对于效率很重要。

最后,我们要做的就是数数。最后,我们可以将其作为复合查询来解决。
> ds[CJ(ids,pos), roll=-Inf, nomatch=0][, .N, by=Pos]
Pos N
1: 1 3
2: 2 3
3: 3 3
4: 4 3
5: 5 2
6: 6 1

关于r - 复杂的汇总功能-是否可以使用R data.table包解决?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20988589/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com