【问题标题】:Subsetting list by values in a column in r按 r 中的列中的值对列表进行子集化
【发布时间】:2021-04-30 12:18:30
【问题描述】:

我想对数据框列表进行子集化,以便它以相同的结构返回列表,但不包括每个数据框中满足一列条件的行。

假设我有以下列表:

col1<- round(rnorm(5, mean = 5), digits = 0)
col2<- round(rnorm(5, mean = 5), digits = 0)
col3<- round(rnorm(5, mean = 5), digits = 0)
a <- data.frame(col1, col2, col3)

col1<- round(rnorm(5, mean = 5), digits = 0)
col2<- round(rnorm(5, mean = 5), digits = 0)
col3<- round(rnorm(5, mean = 5), digits = 0)
b <- data.frame(col1, col2, col3)

col1<- round(rnorm(5, mean = 5), digits = 0)
col2<- round(rnorm(5, mean = 5), digits = 0)
col3<- round(rnorm(5, mean = 5), digits = 0)
c <- data.frame(col1, col2, col3)

my_list <- list(a,b,c)
names(my_list)<-c("df1", "df2", "df3")

这提供了一个列表:

> my_list
$df1
  col1 col2 col3
1    3    6    5
2    5    4    4
3    6    5    6
4    5    3    6
5    4    4    4

$df2
  col1 col2 col3
1    6    5    5
2    6    5    5
3    5    6    6
4    5    4    5
5    6    5    5

$df3
  col1 col2 col3
1    6    7    5
2    6    5    5
3    5    6    4
4    4    6    5
5    5    6    4 

假设我想删除 col3 中值小于 5 的所有行:

> my_list
$df1
  col1 col2 col3
1    3    6    5
3    6    5    6
4    5    3    6


$df2
  col1 col2 col3
1    6    5    5
2    6    5    5
3    5    6    6
4    5    4    5
5    6    5    5

$df3
  col1 col2 col3
1    6    7    5
2    6    5    5
4    4    6    5

我尝试使用 lapply 无济于事:

result <- lapply(my_list, function(x) {
  return(x[x$'col3' < 5])
}
)

> result 
$df1
[1] FALSE  TRUE FALSE FALSE  TRUE

$df2
[1] FALSE FALSE FALSE FALSE FALSE

$df3
[1] FALSE FALSE  TRUE FALSE  TRUE

任何帮助将不胜感激!

【问题讨论】:

  • 缺少逗号? return(x[x$'col3' &lt; 5, ])(使用$时也不需要在“col3”周围加上引号
  • 感谢您指出引号和逗号。更改此设置似乎无法解决问题,但遵循 Yuriy 的以下建议效果很好。
  • 不知道为什么它不应该工作 - 对我来说非常适合。由于缺少 set.seed(),您的示例不是很可重复 - 这可能是原因吗?显然,您需要更改为 x[x$col3 &gt;= 5, ] - 你这样做了吗?
  • 我很抱歉。你是对的,这行得通。

标签: r list dataframe subset


【解决方案1】:

这是tidyverse 解决方案:

library(tidyverse)

result <- function(x) {
  x %>% 
    filter(col3 < 6)
}

map(my_list, result)

这将返回 data.frames 中的 list,其中 col3 小于 6。

$df1
  col1 col2 col3
1    5    4    4
2    4    4    4

$df2
  col1 col2 col3
1    6    7    5

$df3
  col1 col2 col3
1    6    5    5
2    5    5    5
3    5    5    3

您可以使用map_df 组合成一个data.frame

map_df(my_list, result)

这给了我们:

> map_df(my_list, result)
  col1 col2 col3
1    5    4    4
2    4    4    4
3    6    7    5
4    6    5    5
5    5    5    5
6    5    5    3

【讨论】:

    【解决方案2】:

    基础

    set.seed(1)
    l <- lapply(my_list, function(x) subset(x, col3 >= 5))
    l
    #> $df1
    #>   col1 col2 col3
    #> 1    5    5    5
    #> 2    5    5    5
    #> 3    4    4    5
    #> 
    #> $df2
    #>   col1 col2 col3
    #> 1    6    5    7
    #> 2    3    6    5
    #> 4    5    5    5
    #> 
    #> $df3
    #>   col1 col2 col3
    #> 4    4    5    7
    #> 5    7    4    7
    
    do.call(rbind, l)
    #>       col1 col2 col3
    #> df1.1    5    5    5
    #> df1.2    5    5    5
    #> df1.3    4    4    5
    #> df2.1    6    5    7
    #> df2.2    3    6    5
    #> df2.4    5    5    5
    #> df3.4    4    5    7
    #> df3.5    7    4    7
    

    reprex package (v1.0.0) 于 2021-02-05 创建

    【讨论】:

    • 请问你如何将这个列表折叠成一个单独的数据框,就像上面的 tidyverse 解决方案一样,但是使用 base r?
    猜你喜欢
    • 2016-03-20
    • 1970-01-01
    • 1970-01-01
    • 2018-06-16
    • 2014-11-22
    • 1970-01-01
    • 1970-01-01
    • 2020-09-09
    相关资源
    最近更新 更多