0

我在 R 中有以下数据框:

df <- data.frame(name = c('p1_start','p1_end','p2_start','p2_end','p1_start','p1_end','p2_start','p2_end','p1_start','p1_end','p2_start','p2_end','p1_start','p1_end','p2_start','p2_end'),
                 time = c(1,3,5,7,9,11,13,15,17,19,21,23,25,27,29,31),
                 target = c(1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2),
                 comb = c(0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1))

还有另一个数据框:

data <- data.frame(time = c(2,5,8,14,14,20,21,26,28,28),
                   name = c('a','b','c','d','e','f','g','h','i','j'))

因此,如果我们看一下,df我们可以按目标和组合对数据进行排序,我们会注意到基本上存在“组”。例如target=1comb=0有四个条目p1_start,p1_end,p2_start,p2_end,对于所有其他目标/组合组合都是相同的。
另一方面data包含带有time时间戳的条目。

目标:我想基于time.
示例: 的第一个条目data具有time=2发生在 之间的含义p1_startp1_end因此它应该获取值target=1comb=0映射到data数据框。
示例 2data : with的条目time=14发生在 之间p2_startp2_end因此它们应该获取值target=1comb=1映射到data数据框。

想法df:我以为我通过targetand进行迭代,comb并且为它们的每个组合检查是否有data时间介于两者之间的行。第二个可以使用以下命令完成:

data[which(data$time > p1_start & data$time < p2_end),]

一旦我得到这些行,就很容易附加这些值。 问题:我怎么能做迭代?我尝试了以下方法:

df %>% 
group_by(target, comb) %>% 
print(data[which(data$time > df$p1_start & data$time < df$p2_end),]) 

但我收到一个time尚未初始化的错误

4

3 回答 3

0

您的问题最为人所知的是执行non-equi join。我们需要在某个给定数据帧中找到一个范围,该范围对应于一个或多个给定向量中的每个值。这最好由data.table包处理。

我们首先将您df转换为适合执行连接的格式,然后data通过dfwhiletime <= end连接time >= start。这是代码

library(data.table)

setDT(df)[, c("type", "name") := tstrsplit(name, "_", fixed = TRUE)]
df <- dcast(df, ... ~ name, value.var = "time")

cols <- c("target", "comb", "type")
setDT(data)[df, (cols) := mget(paste0("i.", cols)), on = .(time<=end, time>=start)]

之后dcastdf看起来像这样

   target comb type end start
1:      1    0   p1   3     1
2:      1    0   p2   7     5
3:      1    1   p1  11     9
4:      1    1   p2  15    13
5:      2    0   p1  19    17
6:      2    0   p2  23    21
7:      2    1   p1  27    25
8:      2    1   p2  31    29

输出是

> data
    time name target comb type
 1:    2    a      1    0   p1
 2:    5    b      1    0   p2
 3:    8    c     NA   NA <NA>
 4:   14    d      1    1   p2
 5:   14    e      1    1   p2
 6:   20    f     NA   NA <NA>
 7:   21    g      2    0   p2
 8:   26    h      2    1   p1
 9:   28    i     NA   NA <NA>
10:   28    j     NA   NA <NA>
于 2022-01-11T09:32:24.180 回答
0

这是一个tidyverse解决方案:

library(tidyr)
library(dplyr)
df %>% 
  rename(name_df=name) %>% 
  mutate(x = time +1) %>% 
  pivot_longer(
    cols = c(time, x), 
    names_to = "helper",
    values_to = "time"
  ) %>% 
  right_join(data, by="time") %>% 
  select(time, name, target, comb)
    time name  target  comb
   <dbl> <chr>  <dbl> <dbl>
 1     2 a          1     0
 2     5 b          1     0
 3     8 c          1     0
 4    14 d          1     1
 5    14 e          1     1
 6    20 f          2     0
 7    21 g          2     0
 8    26 h          2     1
 9    28 i          2     1
10    28 j          2     1
于 2022-01-11T10:19:06.650 回答
0
df <- data.frame(name = c('p1_start','p1_end','p2_start','p2_end','p1_start','p1_end','p2_start','p2_end','p1_start','p1_end','p2_start','p2_end','p1_start','p1_end','p2_start','p2_end'),
                 time = c(1,3,5,7,9,11,13,15,17,19,21,23,25,27,29,31),
                 target = c(1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2),
                 comb = c(0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1))

data <- data.frame(time = c(2,5,8,14,14,20,21,26,28,28),
                   name = c('a','b','c','d','e','f','g','h','i','j'))

library(fuzzyjoin)
library(tidyverse)

tmp <- df %>%
  separate(name,
           into = c("p", "period"),
           sep = "_",
           remove = TRUE) %>%
  pivot_wider(
    id_cols = c(p, target, comb),
    names_from = period,
    values_from = time
  ) %>%
  select(-p)

fuzzy_left_join(
  x = data, 
  y = tmp, 
  by = c("time" = "start", 
         "time" = "end"), 
  match_fun = list(`>=`, `<=`))
#>    time name target comb start end
#> 1     2    a      1    0     1   3
#> 2     5    b      1    0     5   7
#> 3     8    c     NA   NA    NA  NA
#> 4    14    d      1    1    13  15
#> 5    14    e      1    1    13  15
#> 6    20    f     NA   NA    NA  NA
#> 7    21    g      2    0    21  23
#> 8    26    h      2    1    25  27
#> 9    28    i     NA   NA    NA  NA
#> 10   28    j     NA   NA    NA  NA

reprex 包于 2022-01-11 创建(v2.0.1)

于 2022-01-11T13:16:40.723 回答