简体   繁体   中英

How to filter out rows that have same number for all columns?

I'd like to filter out the rows in a data frame that have same data across all columns in the same row? In this example, I want to identify user_id 1 and 3 . How do I do that?

df <- read_csv("user_id, q1, q2, q3, q4
1, 5, 5, 5, 5
2, 4, 3, 5 ,6
3, 2, 2, 2, 2
4, 5, 4, NA, 4")

Purpose: To identify people who tick the same boxes all questions in questionnaires.

Update: The suggested solution works fine till q1 has NA.

df <- read_csv("user_id, q1, q2, q3, q4
               1, 5, 5, 5, 5
               2, NA, 3, 5 ,6
               3, 2, 2, 2, 2
               4, 5, 4, NA, 4")

You can pick one of the questions, q1 for instance, and compare it with other questions, select if all the questions are equal;

df$user_id[rowSums(df$q1 != df[-1], na.rm=T) == 0]
# [1] 1 3

df %>% filter(rowSums(.[-1] != q1, na.rm=T) == 0)

# A tibble: 2 x 5
#  user_id    q1    q2    q3    q4
#    <int> <int> <int> <int> <int>
#1       1     5     5     5     5
#2       3     2     2     2     2
  • Compare q1 column with other q s columns with .[-1] != q1 , here . is df piped from %>% , .[-1] drops the user_id column;
  • Check how many columns are not equal to q1 by doing rowSums(.[-1] != q1, na.rm=T) ignoring NAs;
  • If non of the columns are not equal q1 , then all the q s columns have the same number, filter based on it;

Unless your data.frame is massive, you can use apply on rows ( MARGIN = 1 )

df$user_id[apply(X = df[,-1], MARGIN = 1, FUN = function(x) length(unique(x)) == 1)]
#[1] 1 3

df[apply(X = df[,-1], MARGIN = 1, FUN = function(x) length(unique(x)) == 1),]
#  user_id q1 q2 q3 q4
#1       1  5  5  5  5
#3       3  2  2  2  2

OR

df$user_id[Reduce(function(x, y) pmax(x, y, na.rm = TRUE), df[,-1]) ==
               Reduce(function(x, y) pmin(x, y, na.rm = TRUE), df[,-1])]
#[1] 1 3

You can solve it with some basic R code.

# Generate your data set
df <- data.frame(user_id =c(1,2,3,4),
                 q1 = c(5,4,2,5),
                 q2 = c(5,3,2,4),
                 q3 = c(5,5,2, NA),
                 q4 = c(5,6,2,4))

# populate the vector with a loop
test <- character(0)
for(i in 1:nrow(df)){
# check if the sum of the values is equal to the sum of the last value 
# repeated. This can only be true if all values are the same
  if(sum(df[i,2:5], na.rm = TRUE) - sum(rep(df[i,5],4)) == 0){
    test[i] <- "equal"
  } else{
    test[i] <- "not_equal"
  }

}

# finally attach the vector as a column to your data frame
df$test <- test

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM