我有一个包含数百个项目的列表,每个项目都有两个值,如下所示:
x <- list(c(123, 4), c(456, 4), c(124, 3), c(157, 3), c(123, 3), c(456, 3))
[[1]]
[1] 123 4
[[2]]
[1] 456 4
[[3]]
[1] 124 3
[[4]]
[1] 157 3
[[5]]
[1] 123 3
[[6]]
[1] 456 3
我想对这些数据做两件事:
1)根据常见的第二个值将其拆分为多个列表,给出:
> x1
[[1]]
[1] 123 4
[[2]]
[1] 456 4
> x2
[[1]]
[1] 124 3
[[2]]
[1] 157 3
[[3]]
[1] 456 3
[[4]]
[1] 123 3
2)根据第一个值将其合并到一个较短的列表中,给出:
> x3
[[1]]
[1] 123 3 4
[[2]]
[1] 456 3 4
[[3]]
[1] 124 3
[[4]]
[1] 157 3
我一直无法弄清楚如何做第二件事,我认为我想到的第一件事却不起作用:
y <- list()
for (i in 1:length(x)) {
if(unique(x[[i]][2])){
# if(x[[i]][2] == 4){
y[[length(y)+1]] <- x[[i]] }}
如果我使用unique()
运行,那么y
将返回与x
相同的效果,这是不合适的。如果我使用散列线运行,那么我得到了正确的结果,但显然只适用于那些[[i]][2] == 4
的情况。我认为unique()
使用可能是错误的,但方向正确。知道该用什么呢?
答案 0 :(得分:2)
我想你想要这个:
x1 <- split(x, sapply(x, function(x) x[[2]]))
和此:
x2 <- split(x, sapply(x, function(x) x[[1]]))
x2 <- lapply(x2, function(x) c(x[[1]][1], unique(sapply(x, function(y) y[[2]]))))
答案 1 :(得分:2)
这是一种使用&#34; data.table&#34;:
的方法library(data.table)
data.table(do.call(rbind, x))[, list(new = list(c(V1, V2))), V1]$new
## [[1]]
## [1] 123 4 3
##
## [[2]]
## [1] 456 4 3
##
## [[3]]
## [1] 124 3
##
## [[4]]
## [1] 157 3
##
答案 2 :(得分:2)
如果你想将它严格保存在列表中,purrr很方便:
library(purrr)
x <- list(c(123, 4), c(456, 4), c(124, 3), c(157, 3), c(123, 3), c(456, 3))
x1 <- split(x, map_dbl(x, 2))
str(x1)
#> List of 2
#> $ 3:List of 4
#> ..$ : num [1:2] 124 3
#> ..$ : num [1:2] 157 3
#> ..$ : num [1:2] 123 3
#> ..$ : num [1:2] 456 3
#> $ 4:List of 2
#> ..$ : num [1:2] 123 4
#> ..$ : num [1:2] 456 4
x2 <- x %>%
split(map_dbl(., 1)) %>%
modify_depth(2, ~.x[-1]) %>%
simplify_all() %>%
imap(~c(as.integer(.y), .x))
str(x2)
#> List of 4
#> $ 123: num [1:3] 123 4 3
#> $ 124: num [1:2] 124 3
#> $ 157: num [1:2] 157 3
#> $ 456: num [1:3] 456 4 3
可能更有用的是,purrr可以快速将列表转换为整洁的数据框,以便您可以通过分组操作完成这些任务:
df_x <- x %>% map_dfr(~list(x = .x[1], y = .x[2]))
# or equivalent but more programmatic,
df_x <- x %>% map_dfr(compose(as.list, set_names), c('x', 'y'))
df_x
#> # A tibble: 6 x 2
#> x y
#> <dbl> <dbl>
#> 1 123 4.00
#> 2 456 4.00
#> 3 124 3.00
#> 4 157 3.00
#> 5 123 3.00
#> 6 456 3.00
通过dplyr::group_by
和summarise
或tidyr::nest
或您有什么。
答案 3 :(得分:1)
我建议将数据整形为data.frame(或tidyverse tibble)
library(tidyverse)
x = list(c(123, 4), c(456, 4), c(124, 3), c(157, 3), c(123, 3), c(456, 3))
first = vapply(x, `[[`, numeric(1), 1)
second = vapply(x, `[[`, numeric(1), 2)
elt = seq_along(x)
tbl = tibble(elt = elt, first = first, second = second)
并对此进行操作,或许重新考虑是否需要'单独列表'等。例如,group_by()
强制分组,summarize()
形成包含第二个元素列表的列
tbl %>% group_by(first) %>% summarize(values=list(second))
...但是,summarize()
语句创建的列表列现在在后续工作流程中是多余的?例如,按组分列的计数和均值为summarize(n = n(), mean = mean(second))
。