首页 > 解决方案 > 在数据帧之间进行比较以在两个数据帧中的相同位置找到观察值的 +/- 1

问题描述

我在时间点 1 和时间点 2 有两个数据帧。每个数据帧都有一个“中点”列,我想将数据帧 2(时间点 2)中的中点与中点数据帧 1(时间点 1)进行比较,这样如果它在 +/- 1 内,在名为“id”的列中为每个在上述参数下返回 TRUE 的比较分配一个唯一的“id”。如果它是假的,那么 id 应该是空白或 0。到目前为止,我一直在玩 ifelse() 函数,但收效甚微。我一直在尝试创建一个函数,以便数据帧时间点 n 与前一个时间点 (n-1) 进行比较。

我最终将使用 purrr 包为每个时间点(总共 130 次)循环它,以了解我为什么这样做的一些背景。

忽略最大和最小列,这些与不同的东西有关,感谢任何可能的帮助!

数据框 1(时间点 1)

structure(list(Object = c(2666L, 2668L, 2671L, 2674L, 2676L, 
2677L, 2678L, 2679L, 2680L, 2682L, 2683L, 2684L, 2685L, 2686L, 
2687L, 2689L, 2692L, 2693L, 2694L, 2695L, 2696L), minimum = c(4L, 
39L, 147L, 224L, 419L, 531L, 595L, 641L, 669L, 723L, 810L, 836L, 
907L, 978L, 1061L, 1129L, 1290L, 1519L, 1749L, 1843L, 1897L), 
    maximum = c(22L, 85L, 173L, 242L, 449L, 587L, 627L, 655L, 
    702L, 740L, 828L, 890L, 923L, 1024L, 1086L, 1144L, 1302L, 
    1544L, 1780L, 1870L, 1925L), midpoint = c(13, 62, 160, 233, 
    434, 559, 611, 648, 685.5, 731.5, 819, 863, 915, 1001, 1073.5, 
    1136.5, 1296, 1531.5, 1764.5, 1856.5, 1911)), row.names = c(NA, 
-21L), class = c("tbl_df", "tbl", "data.frame"))

数据框 2(时间点 2)

structure(list(Object = c(2645L, 2646L, 2650L, 2652L, 2655L, 
2656L, 2657L, 2658L, 2659L, 2661L, 2662L, 2663L, 2664L, 2665L, 
2667L, 2670L, 2675L, 2681L, 2688L, 2690L, 2691L), minimum = c(4L, 
40L, 147L, 224L, 415L, 532L, 595L, 641L, 670L, 722L, 811L, 835L, 
907L, 978L, 1061L, 1128L, 1289L, 1520L, 1748L, 1843L, 1897L), 
    maximum = c(22L, 85L, 173L, 242L, 445L, 588L, 627L, 655L, 
    702L, 739L, 828L, 891L, 923L, 1022L, 1085L, 1143L, 1302L, 
    1544L, 1779L, 1870L, 1925L), midpoint = c(13, 62.5, 160, 
    233, 430, 560, 611, 648, 686, 730.5, 819.5, 863, 915, 1000, 
    1073, 1135.5, 1295.5, 1532, 1763.5, 1856.5, 1911)), row.names = c(NA, 
-21L), class = c("tbl_df", "tbl", "data.frame"))

预期输出:

object minimum maximum midpoint id
2645      4       22       13    1
2646     40       85      62.5   2
2650     147      173     260    3

因此,输出是数据帧 2 的附加列,每个实例都有一个唯一 ID,其中观察 1(在 df2 中)的中点在观察 1(在 df1 中)的 +/- 1 范围内。因为我想与第 n-1 个数据帧进行比较,因为它代表上一个时间点。

标签: r

解决方案


您可以对所需范围内的df2行进行子集化,将该子集化数据框存储为新数据框,并向其中添加一列:df2$midpointdf1$midpointid

df2new <- df2[df2$midpoint >= df1$midpoint - 1 & df2$midpoint <= df2$midpoint + 1, ]
df2new$id <- 1:nrow(df2new)

df2new
# A tibble: 20 x 5
   Object minimum maximum midpoint    id
    <int>   <int>   <int>    <dbl> <int>
 1   2645       4      22     13       1
 2   2646      40      85     62.5     2
 3   2650     147     173    160       3
 4   2652     224     242    233       4
 5   2656     532     588    560       5
 6   2657     595     627    611       6
 7   2658     641     655    648       7
 8   2659     670     702    686       8
 9   2661     722     739    730.      9
10   2662     811     828    820.     10
11   2663     835     891    863      11
12   2664     907     923    915      12
13   2665     978    1022   1000      13
14   2667    1061    1085   1073      14
15   2670    1128    1143   1136.     15
16   2675    1289    1302   1296.     16
17   2681    1520    1544   1532      17
18   2688    1748    1779   1764.     18
19   2690    1843    1870   1856.     19
20   2691    1897    1925   1911      20

或者,如果您想保持df2原样,但用 '标记'那些落入所需范围的行1和那些不属于 ' 的行0,你可以这样做:

df2$id <-ifelse(df2$midpoint >= df1$midpoint - 1 & df2$midpoint <= df2$midpoint + 1, 1, 0)
df2
# A tibble: 21 x 5
   Object minimum maximum midpoint    id
    <int>   <int>   <int>    <dbl> <dbl>
 1   2645       4      22     13       1
 2   2646      40      85     62.5     1
 3   2650     147     173    160       1
 4   2652     224     242    233       1
 5   2655     415     445    430       0
 6   2656     532     588    560       1
 7   2657     595     627    611       1
 8   2658     641     655    648       1
 9   2659     670     702    686       1
10   2661     722     739    730.      1
# … with 11 more rows

...并且如果您希望有一个连续的id值范围仍然标记该范围之外的行(因为它只是前一个的重复id),那么使用cumsumon id

df2$id2 <- cumsum(df2$id)
df2$id2[df2$id < 1] <- 0   # keep the `id` value `0`:

获得这个:

df2
# A tibble: 21 x 6
   Object minimum maximum midpoint    id   id2
    <int>   <int>   <int>    <dbl> <dbl> <dbl>
 1   2645       4      22     13       1     1
 2   2646      40      85     62.5     1     2
 3   2650     147     173    160       1     3
 4   2652     224     242    233       1     4
 5   2655     415     445    430       0     0
 6   2656     532     588    560       1     5
 7   2657     595     627    611       1     6
 8   2658     641     655    648       1     7
 9   2659     670     702    686       1     8
10   2661     722     739    730.      1     9 
# … with 11 more rows

推荐阅读