将 df 拆分为包含不带 nas 的值组的列表

Jam*_*mes 5 r dplyr

我正在处理来自 GeomLine 对象的比例数据。在此我试图找到不相交线的数据。

数据可能看起来像这样

structure(list(x = c(96, 150, 150, 157, 163, 165, 165, 165, 166, 
    167, 168, 170, 178, 178, 184, 213), y = c(NA, 49, NA, NA, 
    NA, 75, NA, 45, 50, NA, 55, 56.2, 55, 57, 50, NA)), class = "data.frame", 
    row.names = c(NA, -16L))
#>      x    y
#> 1   96   NA
#> 2  150 49.0
#> 3  150   NA
#> 4  157   NA
#> 5  163   NA
#> 6  165 75.0
#> 7  165   NA
#> 8  165 45.0
#> 9  166 50.0
#> 10 167   NA
#> 11 168 55.0
#> 12 170 56.2
#> 13 178 55.0
#> 14 178 57.0
#> 15 184 50.0
#> 16 213   NA
Run Code Online (Sandbox Code Playgroud)

我需要找到至少有两个连续行且没有 NA 的数据组。然后将其转换为具有这些值的 df 列表。

我已经让它看起来像这样:

dplyr::filter(tidyr::drop_na(dplyr::mutate(structure(list(x = c(96, 
    150, 150, 157, 163, 165, 165, 165, 166, 167, 168, 170, 178, 
    178, 184, 213), y = c(NA, 49, NA, NA, NA, 75, NA, 45, 50, 
    NA, 55, 56.2, 55, 57, 50, NA)), class = "data.frame", row.names = c(NA, 
    -16L)), row_id = dplyr::row_number()), y), row_id == dplyr::lead(row_id) - 
    1 | row_id == dplyr::lag(row_id) + 1)
#>     x    y row_id
#> 1 165 45.0      8
#> 2 166 50.0      9
#> 3 168 55.0     11
#> 4 170 56.2     12
#> 5 178 55.0     13
#> 6 178 57.0     14
#> 7 184 50.0     15
Run Code Online (Sandbox Code Playgroud)

这是我正在努力应对的实际转变。

我似乎找不到办法做到这一点。我尝试过进行更多的突变以使其达到我可以使用的程度group_split,但我似乎无法达到这一点。

这就是我想要的最终结果。

list(data.frame(x = c(165, 166), y = c(45, 50)), data.frame(x = c(168, 
    170, 178, 178, 184), y = c(55, 56.2, 55, 57, 50)))
#> [[1]]
#>     x  y
#> 1 165 45
#> 2 166 50
#> 
#> [[2]]
#>     x    y
#> 1 168 55.0
#> 2 170 56.2
#> 3 178 55.0
#> 4 178 57.0
#> 5 184 50.0
Run Code Online (Sandbox Code Playgroud)

编辑:

感谢答案的帮助,特别是@SALAR,我仅使用 dplyr 和 base R 想出了这个解决方案

lineData |> 
          group_by(group = cumsum(is.na(y))) |>
          filter(!(is.na(y) & n() > 1)) |> 
          group_split() |>
          Filter(function(x) nrow(x) >= 2, x = _)
Run Code Online (Sandbox Code Playgroud)

SAL*_*SAL 2

您可以使用 tidyverse 系列来做到这一点:

\n
df %>% \n  # Group the data frame by consecutive NAs in the `y` column\n  group_by(group = cumsum(is.na(y))) %>%\n  # Remove groups that have more than one NA in the `y` column\n  filter(!(is.na(y) & n() > 1)) %>% \n  # Split the data frame into a list of data frames based on the groups\n  split(.$group) %>% \n  # Keep only those data frames with more than two rows\n  keep(~nrow(.) >= 2)\n
Run Code Online (Sandbox Code Playgroud)\n

输出:

\n
$`5`\n# A tibble: 2 \xc3\x97 3\n# Groups:   group [1]\n      x     y group\n  <dbl> <dbl> <int>\n1   165    45     5\n2   166    50     5\n\n$`6`\n# A tibble: 5 \xc3\x97 3\n# Groups:   group [1]\n      x     y group\n  <dbl> <dbl> <int>\n1   168  55       6\n2   170  56.2     6\n3   178  55       6\n4   178  57       6\n5   184  50       6\n
Run Code Online (Sandbox Code Playgroud)\n