【问题标题】:R Looping through columns of data frame, filtering by each columnR循环遍历数据框的列,按每列过滤
【发布时间】:2020-11-05 23:08:07
【问题描述】:

我有一个查看数据输入错误的数据框。 它有两组变量:

  1. 一组是错误标志(它们的名称将包含“错误”)。
  2. 一组是有关已标记案例的信息(对于本示例,为“值”列)。

我想循环遍历错误标志变量,在每列中按值 1 过滤数据框,然后打印。

我的问题是我无法让 R 将列的名称识别为要过滤的名称。 我已经寻找其他示例,但我没有达到我需要的。

在此示例中,我有一个数据框“test_df”,其中包含四个变量:error_1-error_3 和值。 我想遍历这三个错误变量,并为值为 1 的行过滤 test_df。

# set up libraries:
library(tidyverse)
library(magrittr)
# Create the data set 'test_df':
test_df <- structure(list(error_1 = c(0, 0, 1, 1), error_2 = c(0, 0, 1, 
1), error_3 = c(0, 0, 1, 1), values = c(1, 2, 3, 4)), class = "data.frame", row.names = c(NA, 
-4L))
#  Pull the column names from test_df, retaining only those with 'error' in their name, and print:

names_test_df <- test_df %>%
  dplyr::select(.,contains("error")) %>%
  names()

test_df

names_test_df



> test_df
  error_1 error_2 error_3 values
1       0       0       0      1
2       0       0       0      2
3       1       1       1      3
4       1       1       1      4

> names_test_df
[1] "error_1" "error_2" "error_3"

这就是麻烦的开始——我不知道如何将 names_test_df 的元素输入到函数中,以便将它们识别为 test_df 中的列名:

test_df %>% dplyr::filter(.,error_1==1)
test_df %>% dplyr::filter(.,as.character(names_test_df[1])==1)
test_df %>% dplyr::filter(.,noquote(names_test_df[1])==1)


> test_df %>% dplyr::filter(.,error_1==1)
  error_1 error_2 error_3 values
1       1       1       1      3
2       1       1       1      4
> test_df %>% dplyr::filter(.,as.character(names_test_df[1])==1)
[1] error_1 error_2 error_3 values 
<0 rows> (or 0-length row.names)
> test_df %>% dplyr::filter(.,noquote(names_test_df[1])==1)
[1] error_1 error_2 error_3 values 
<0 rows> (or 0-length row.names)

我也玩过 colnames(test_df) 中的“item”循环,得到了相同的结果。

有人可以就如何做到这一点提供一些指导吗?

【问题讨论】:

    标签: r


    【解决方案1】:

    我们可以将字符串转换为symbol 并计算 (!!)

    library(dplyr)
    test_df %>%
         dplyr::filter(., !! rlang::sym(names_test_df[1])==1)
    #  error_1 error_2 error_3 values
    #1       1       1       1      3
    #2       1       1       1      4
    

    或者across的另一个选项

    test_df %>%
         filter(across(all_of(names_test_df[1]), ~ . == 1))
    #  error_1 error_2 error_3 values
    #1       1       1       1      3
    #2       1       1       1      4
    

    【讨论】:

      【解决方案2】:

      在基础 R 中,您可以使用 [ 对列进行子集化。对于一列,您可以这样做:

      test_df[test_df[names_test_df[1]] == 1, ]
      
      #  error_1 error_2 error_3 values
      #3       1       1       1      3
      #4       1       1       1      4
      

      对于多个列,我们要选择其中任何一列中包含 1 的行。

      test_df[rowSums(test_df[names_test_df] == 1) > 0, ]
      

      【讨论】:

        猜你喜欢
        • 2018-09-28
        • 1970-01-01
        • 2021-02-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-02-04
        相关资源
        最近更新 更多