R:基于来自另一数据帧的条件对数据帧进行子集化

时间:2013-06-18 09:21:23

标签: r dataframe subset

这是我想要解决的问题。比如说,我有两个数据框,如下所示:

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的列,用于链接数据帧。我希望从measurement时间observationss for which时间1 is between时间2 and采样时间from the位置`获得data frame. Additionally, I'd like to connect the appropriate次到每次测量。

我已成功完成此操作,方法是将sampletimes转换为宽格式(即time1每个条目一行中的所有time2id信息,合并id变量的两个数据帧,并使用条件语句仅采用time落在行中至少一个时间间隔之间的实例,然后将location分配给observations适当的测量。

但是,我在id中有大约200万行,这样做需要很长时间。我正在寻找一种更好的方式来保持数据的长格式。示例数据集非常简单,但实际上,我的数据包含每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 个可变数量的间隔和位置。

对于我们的例子,我希望得到的数据框如下:

{{1}}

2 个答案:

答案 0 :(得分: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

答案 1 :(得分: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

修改

由于您的行数超过5百万,因此您应尝试使用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]