基于另一个数据框的条件,对数据框进行子集筛选

3

我正在尝试解决的问题是:假设我有两个数据框,如下所示:

observations <- data.frame(id = rep(rep(c(1,2,3,4), each=5), 5),
    time = c(rep(1:5,4), rep(6:10,4), rep(11:15,4), rep(16:20,4), rep(21:25,4)),
    measurement = rnorm(100,5,7))

sampletimes <- data.frame(location = letters[1:20], 
    id = rep(1:4,5),
    time1 = rep(c(2,7,12,17,22), each=4), 
    time2 = rep(c(4,9,14,19,24), each=4))

它们都包含名为id的列,用于链接数据框。我想从sampletimes数据框中获取time1time2之间的observationssmeasurement。此外,我想将适当的location连接到每个测量值。
我已经成功地将我的sampletimes转换为宽格式(即每个条目的所有time1time2信息在一行中),通过id变量合并两个数据框,并使用条件语句仅在时间间隔中的至少一个时间段内才采取实例,然后将location分配给适当的测量值。
然而,我的observations表格中有大约200万行数据,这样做需要很长时间。我正在寻找一种更好的方法来保持数据的长格式。示例数据集非常简单,但实际上,我的数据包含每个id的可变数量的间隔和位置。
对于我们的示例,我希望得到的数据框如下:
id time measurement letters[1:20]
1    3  10.5163892             a
2    3   5.5774119             b
3    3  10.5057060             c
4    3  14.1563179             d
1    8   2.2653761             e
2    8  -1.0905546             f
3    8  12.7434161             g
4    8  17.6129261             h
1   13  10.9234673             i
2   13   1.6974481             j
3   13  -0.3664951             k
4   13  13.8792198             l
1   18   6.5038847             m
2   18   1.2032935             n
3   18  15.0889469             o
4   18   0.8934357             p
1   23   3.6864527             q
2   23   0.2404074             r
3   23  11.6028766             s
4   23  20.7466908             t
2个回答

4
这里有一个使用merge的建议:
# merge both data frames
dat <- merge(observations, sampletimes, by = "id")
# extract valid rows
dat2 <- dat[dat$time > dat$time1 & dat$time < dat$time2, seq(4)]
# sort
dat2[order(dat2$time, dat2$id), ]

结果如下:
    id time measurement location
11   1    3    7.086246        a
141  2    3    6.893162        b
251  3    3   16.052627        c
376  4    3   -6.559494        d
47   1    8   11.506810        e
137  2    8   10.959782        f
267  3    8   11.079759        g
402  4    8   11.082015        h
83   1   13    5.584257        i
218  2   13   -1.714845        j
283  3   13  -11.196792        k
418  4   13    8.887907        l
99   1   18    1.656558        m
234  2   18   16.573179        n
364  3   18    6.522298        o
454  4   18    1.005123        p
125  1   23   -1.995719        q
250  2   23   -6.676464        r
360  3   23   10.514282        s
490  4   23    3.863357        t

3

虽然不是特别高效,但是能够完成工作:

 subset(merge(observations,sampletimes), time > time1 & time < time2)
        id time measurement location time1 time2
    11   1    3    3.180321        a     2     4
    47   1    8    6.040612        e     7     9
    83   1   13   -5.999317        i    12    14
    99   1   18    2.689414        m    17    19
    125  1   23   12.514722        q    22    24
    137  2    8    4.420679        f     7     9
    141  2    3   11.492446        b     2     4
    218  2   13    6.672506        j    12    14
    234  2   18   12.290339        n    17    19
    250  2   23   12.610828        r    22    24
    251  3    3    8.570984        c     2     4
    267  3    8   -7.112291        g     7     9
    283  3   13    6.287598        k    12    14
    360  3   23   11.941846        s    22    24
    364  3   18   -4.199001        o    17    19
    376  4    3    7.133370        d     2     4
    402  4    8   13.477790        h     7     9
    418  4   13    3.967293        l    12    14
    454  4   18   12.845535        p    17    19
    490  4   23   -1.016839        t    22    24

编辑

由于您有超过500万行数据,建议尝试使用data.table来解决问题:

library(data.table)
OBS <- data.table(observations)
SAM <- data.table(sampletimes)
merge(OBS,SAM,allow.cartesian=TRUE,by='id')[time > time1 & time < time2]

最初,这个解决方案是有效的。然而,当我增加了观测数据框的大小到大约500万行时,它就无法工作了。我收到了以下错误信息:Error: evaluation nested too deeply: infinite recursion / options(expressions=)?。我尝试的每个其他命令都产生了相同的错误消息。 - Jota
@Frank 我编辑了我的解决方案,提供了一个 data.table 的方案。如果你还是出现相同的错误,请让我知道。 - agstudy
我的时间是以POSIXlt格式表示的,但它不起作用,因为data.table不支持POSIXlt。一旦我将我的时间列转换为POSIXct,它就可以工作了。 - Jota
1
@Frank 处理 500万行数据?最好使用 POSIXct,它是数字类型。POSIXlt 是一个列表,只在想要对日期时间进行子集操作时使用(获取小时、天、月等)。 - agstudy

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