Filter kolom dataframe yang berisi vektor
Saya ingin memfilter kolom yang berisi vektor di seluruh konten sel. Saya telah melihat R dplyr. Filter kerangka data yang berisi kolom vektor numerik , tetapi kebutuhan saya sedikit berbeda.
Contoh df (reprex lengkap di bawah)
df <- tibble::tribble(
~id, ~len, ~vec,
1L, 1L, 1L,
2L, 2L, 1:2,
3L, 2L, c(1L, 2L),
4L, 3L, c(1L, 2L, 3L),
5L, 3L, 1:3,
6L, 3L, c(1L, 3L, 2L),
7L, 3L, c(3L, 2L, 1L),
8L, 3L, c(1L, 3L, 2L),
9L, 4L, c(1L, 2L, 4L, 3L),
10L, 3L, c(3L, 2L, 1L)
)
memberi (kode warna untuk pertandingan)
Saya dapat mengelompokkan_ berdasarkan kolom vec:
dfg <- df %>%
group_by(vec) %>%
summarise(n = n()
,total_len = sum(len))
Untuk sel individu, perbandingan langsung tidak berfungsi, tetapi identik berfungsi :
df$vec[4] == df$vec[5]
#> Error in df$vec[4] == df$vec[5]: comparison of these types is not implemented
identical(df$vec[4], df$vec[5])
#> [1] TRUE
Tetapi tidak ada padanan yang berfungsi dalam filter , yang saya butuhkan:
df %>% filter(vec == c(1L, 2L, 3L))
#> Warning in vec == c(1L, 2L, 3L): longer object length is not a multiple of
#> shorter object length
#> Error: Problem with `filter()` input `..1`.
#> x 'list' object cannot be coerced to type 'integer'
#> i Input `..1` is `vec == c(1L, 2L, 3L)`.
df %>% filter(identical(vec, c(1L, 2L, 3L)))
#> # A tibble: 0 x 3
#> # ... with 3 variables: id <int>, len <int>, vec <list>
df %>% filter(identical(vec, vec[5]))
#> # A tibble: 0 x 3
#> # ... with 3 variables: id <int>, len <int>, vec <list>
Saya yakin ada solusi sederhana yang saya lewatkan.
Kebutuhan yang lebih maju adalah mencocokkan tempat konten sel cocok dalam urutan apa pun, sehingga 6 sel yang disorot oranye, ungu, dan emas di atas semuanya akan cocok. Solusi yang juga berfungsi dengan list serta vektor juga akan bagus karena ini mungkin merupakan kebutuhan masa depan.
Reprex penuh:
library(tibble)
library(dplyr)
#>
#> Attaching package: 'dplyr'
#> The following objects are masked from 'package:stats':
#>
#> filter, lag
#> The following objects are masked from 'package:base':
#>
#> intersect, setdiff, setequal, union
df <- tibble::tribble(
~id, ~len, ~vec,
1L, 1L, 1L,
2L, 2L, 1:2,
3L, 2L, c(1L, 2L),
4L, 3L, c(1L, 2L, 3L),
5L, 3L, 1:3,
6L, 3L, c(1L, 3L, 2L),
7L, 3L, c(3L, 2L, 1L),
8L, 3L, c(1L, 3L, 2L),
9L, 4L, c(1L, 2L, 4L, 3L),
10L, 3L, c(3L, 2L, 1L)
)
df
#> # A tibble: 10 x 3
#> id len vec
#> <int> <int> <list>
#> 1 1 1 <int [1]>
#> 2 2 2 <int [2]>
#> 3 3 2 <int [2]>
#> 4 4 3 <int [3]>
#> 5 5 3 <int [3]>
#> 6 6 3 <int [3]>
#> 7 7 3 <int [3]>
#> 8 8 3 <int [3]>
#> 9 9 4 <int [4]>
#> 10 10 3 <int [3]>
dfg <- df %>%
group_by(vec) %>%
summarise(n = n()
,total_len = sum(len))
#> `summarise()` ungrouping output (override with `.groups` argument)
dfg
#> # A tibble: 6 x 3
#> vec n total_len
#> <list> <int> <int>
#> 1 <int [1]> 1 1
#> 2 <int [2]> 2 4
#> 3 <int [3]> 2 6
#> 4 <int [3]> 2 6
#> 5 <int [3]> 2 6
#> 6 <int [4]> 1 4
df$vec[4] == df$vec[5]
#> Error in df$vec[4] == df$vec[5]: comparison of these types is not implemented
identical(df$vec[4], df$vec[5])
#> [1] TRUE
df %>% filter(vec == c(1L, 2L, 3L))
#> Warning in vec == c(1L, 2L, 3L): longer object length is not a multiple of
#> shorter object length
#> Error: Problem with `filter()` input `..1`.
#> x 'list' object cannot be coerced to type 'integer'
#> i Input `..1` is `vec == c(1L, 2L, 3L)`.
df %>% filter(identical(vec, c(1L, 2L, 3L)))
#> # A tibble: 0 x 3
#> # ... with 3 variables: id <int>, len <int>, vec <list>
df %>% filter(identical(vec, vec[5]))
#> # A tibble: 0 x 3
#> # ... with 3 variables: id <int>, len <int>, vec <list>
Created on 2021-01-13 by the reprex package (v0.3.0)
Jawaban
Lempar rowwise
dan juga periksa length
vektor untuk dibandingkan untuk menghindari peringatan.
library(dplyr)
compare <- c(1L, 2L, 3L)
df %>%
rowwise() %>%
filter(length(vec) == length(compare) && all(vec == compare))
# id len vec
# <int> <int> <list>
#1 4 3 <int [3]>
#2 5 3 <int [3]>
Kita bisa lihat filter
panjangnya dulu yang mungkin lebih cepat pada dataset yang lebih besar.
df %>%
filter(lengths(vec) == length(compare)) %>%
rowwise() %>%
filter(all(vec == compare))
Logika serupa di basis R:
subset(df, sapply(vec, function(x)
length(x) == length(compare) && all(x == compare)))
Kita bisa menggunakan map
library(dplyr)
library(purrr)
compare <- c(1L, 2L, 3L)
df %>%
filter(map_lgl(vec, ~ length(.x) == length(compare) && all(.x == compare)))
# A tibble: 2 x 3
# id len vec
# <int> <int> <list>
#1 4 3 <int [3]>
#2 5 3 <int [3]>