[英]How to subset windows in a dataframe using start- and end-values from another dataframe in R?
我有一個時間序列數據df1
的 dataframe ,我需要從 R 中提取多個“窗口”。 我需要的 windows 的起點和終點位於單獨的 dataframe, df2
的兩列中。 起點和終點的值對應於所需的 windows 的行號。
在下面的示例中,我是解決方案的一部分,但目前只提取了第一個 window。 如何修改此示例以提取所有四個 windows? 這可能是purrr的情況嗎?
library(tidyverse)
# dataframe of data to subset
df1 <- tibble(my_values = rnorm(100))
# dataframe of windows (i.e. row number IDs) to extract from data
df2 <-tibble::tribble(
~window_start, ~window_end,
3L, 10L,
21L, 25L,
52L, 63L,
78L, 90L
)
# extracted data
df3 <- df1 %>%
slice(df2$window_start : df2$window_end)
(注意。我知道這里有一個類似的問題 - 使用來自另一個 dataframe 的起點和終點對 dataframe 進行子集? - 但我的實際數據非常大,我很好奇非基於合並的解決方案是否會更快。)
也許用purrr::map2
試試這種方法
# dataframe of data to subset
df1 <- tibble(my_values = rnorm(100, mean = 45, sd = 30) %>% abs())
# dataframe of windows (i.e. row number IDs) to extract from data
df2 <-tibble::tribble(
~window_start, ~window_end,
3L, 10L,
21L, 25L,
52L, 63L,
78L, 90L
)
subset_thats_in <- function(mini, maxi){
df1 %>%
filter(between(my_values, mini, maxi))
}
purrr::map2(df2$window_start,
df2$window_end,
subset_thats_in)
[[1]]
# A tibble: 4 × 1
my_values
<dbl>
1 6.47
2 8.69
3 7.73
4 7.35
[[2]]
# A tibble: 12 × 1
my_values
<dbl>
1 24.2
2 22.9
3 22.4
4 24.4
5 22.6
6 21.7
7 23.2
8 21.3
9 23.3
10 21.1
11 23.5
12 22.6
[[3]]
# A tibble: 10 × 1
my_values
<dbl>
1 54.0
2 61.4
3 62.5
4 60.8
5 60.5
6 55.5
7 61.4
8 59.0
9 57.9
10 53.3
[[4]]
# A tibble: 6 × 1
my_values
<dbl>
1 87.8
2 79.1
3 80.5
4 82.7
5 85.2
6 80.6
你可以使用mapply
:
df1[unlist(mapply(function(x,y) x:y, df2$window_start, df2$window_end)),]
# A tibble: 38 x 1
my_values
<dbl>
1 0.671
2 -0.617
3 -0.354
4 2.76
5 0.382
6 -0.488
7 0.889
8 -1.32
9 0.328
10 0.779
# ... with 28 more rows
purrr
對於此類數據轉換非常有效。 但是,如果要復制數據,長度為 10000 的列表可能仍然很強大。
x = vector(mode = "list", 10000L)
x = transpose(df2) %>% map(function(x){x = as.numeric(x); df1[x[1]:x[2],]})
as.numeric
在轉置列表上獲取范圍,可用於對 df1 進行子集化。
我們可以使用map2
library(tidyverse)
map2(df2[[1]], df2[[2]], ~ df1[.x:.y, ])
#> [[1]]
#> # A tibble: 8 × 1
#> my_values
#> <dbl>
#> 1 1.33
#> 2 1.27
#> 3 0.415
#> 4 -1.54
#> 5 -0.929
#> 6 -0.295
#> 7 -0.00577
#> 8 2.40
#>
#> [[2]]
#> # A tibble: 5 × 1
#> my_values
#> <dbl>
#> 1 -0.224
#> 2 0.377
#> 3 0.133
#> 4 0.804
#> 5 -0.0571
#>
#> [[3]]
#> # A tibble: 12 × 1
#> my_values
#> <dbl>
#> 1 -0.377
#> 2 2.44
#> 3 -0.795
#> 4 -0.0549
#> 5 0.250
#> 6 0.618
#> 7 -0.173
#> 8 -2.22
#> 9 -1.26
#> 10 0.359
#> 11 -0.0110
#> 12 -0.941
#>
#> [[4]]
#> # A tibble: 13 × 1
#> my_values
#> <dbl>
#> 1 -0.118
#> 2 -0.912
#> 3 -1.44
#> 4 -0.797
#> 5 1.25
#> 6 0.772
#> 7 -0.220
#> 8 -0.425
#> 9 -0.419
#> 10 0.997
#> 11 -0.276
#> 12 1.26
#> 13 0.647
或者創造性地使用 dplyr。
df2 %>%
rowwise() %>%
transmute(windows = list(c_across(starts_with("window")) %>% {df1[.[[1]]:.[[2]], ]}))
#> # A tibble: 4 × 1
#> # Rowwise:
#> windows
#> <list>
#> 1 <tibble [8 × 1]>
#> 2 <tibble [5 × 1]>
#> 3 <tibble [12 × 1]>
#> 4 <tibble [13 × 1]>
由代表 package (v2.0.1) 於 2022 年 1 月 9 日創建
數據:
set.seed(0)
# dataframe of data to subset
df1 <- tibble(my_values = rnorm(100))
# dataframe of windows (i.e. row number IDs) to extract from data
df2 <- tibble::tribble(
~window_start, ~window_end,
3L, 10L,
21L, 25L,
52L, 63L,
78L, 90L
)
一個簡單的基本 R 解決方案將使用sequence
function 生成您需要子集 dataframe 的所有行索引。 sequence 的第一個參數指定要生成的sequence
的長度,每個從第二個參數中給出的數字開始。 這應該非常有效,因為 function 所做的唯一事情就是創建一個整數序列。
df1[sequence(df2$window_end - df2$window_start + 1L, df2$window_start), ]
Output
> set.seed(1234L)
> df1 <- tibble(my_values = rnorm(100))
> df1[sequence(df2$window_end - df2$window_start + 1L, df2$window_start), ]
# A tibble: 38 x 1
my_values
<dbl>
1 1.08
2 -2.35
3 0.429
4 0.506
5 -0.575
6 -0.547
7 -0.564
8 -0.890
9 0.134
10 -0.491
# ... with 28 more rows
您還可以通過使用data.table:::vecseq
獲得較小的性能改進。 代碼與上面幾乎相同:
df1[data.table:::vecseq(df2$window_start, df2$window_end - df2$window_start + 1L, NULL), ]
延伸閱讀: data.table高效回收V2
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.