R: выберите строки во фрейме данных, которые содержат как положительные, так и отрицательные значения

#r #dataframe #dplyr #integer #subset

#r #фрейм данных #дплыр #целое число #подмножество #dplyr #целое

Вопрос:

У меня есть фрейм данных в R, который содержит несколько столбцов. Значения в этих столбцах могут быть отрицательными или положительными. В результате у меня есть строки, где все значения положительны, строки, где все значения отрицательны, и строки как с положительными, так и с отрицательными значениями. Я хочу извлечь только те строки, которые имеют как положительные, так и отрицательные значения, которые не равны нулю.

Давайте сделаем это с фиктивным набором данных:

 x <- data.frame("contrast_1" = c(-1.2,1.3,1.4,-1.2,0), "contrast_2" = c(-1.8,2.3,2.4,0.02,-8), "contrast_3" = c(-0.23,-4.5,0.4,-0.24,-1.23))
row.names(x) <- c('gene_1', 'gene_2', 'gene_3', 'gene_4', 'gene_5')
  

Фрейм данных выглядит следующим образом:

        contrast_1 contrast_2 contrast_3
gene_1       -1.2      -1.80      -0.23
gene_2        1.3       2.30      -4.50
gene_3        1.4       2.40       0.40
gene_4       -1.2       0.02      -0.24
gene_5        0.0      -8.00      -1.23
  

В этом фрейме данных гены 2 и 4 содержат как положительные, так и отрицательные значения: это строки, которые я хочу извлечь. Ген 5 содержит отрицательные значения и нулевое значение. Я не хочу ген 5.

Я решил эту проблему с помощью следующего кода:

 library(dplyr) 

#select all the rows that only have positive values
x_UP = x %>% filter_at(colnames(x), all_vars(. >= 0))

#select all the rows that only have negative values
x_DOWN = x %>% filter_at(colnames(x), all_vars(. <= 0))

#combine the data frames    
removed = rbind(x_UP,x_DOWN)

#remove the rows with only positive or only negative values from data frame x
subset = x [!row.names(x)%in%rownames(removed),]
  

Результат выглядит примерно так:

        contrast_1 contrast_2 contrast_3
gene_2        1.3       2.30      -4.50
gene_4       -1.2       0.02      -0.24
  

Как вы можете видеть, этот код работает, потому что в нем выбраны только гены 2 и 4. Тем не менее, я чувствую, что должен быть в состоянии выполнить это более элегантным способом. Отсюда мой вопрос к вам: есть ли лучшие способы сделать это? Меня больше всего интересует решение, которое могло бы сразу выбрать все строки, имеющие как положительные, так и отрицательные значения, вместо того, чтобы сначала извлекать строки, которые имеют только положительные или только отрицательные значения.

Уже спасибо!

Ответ №1:

Опция с sign с all . Мы могли бы использовать c_across with filter после выполнения rowwise

 library(dplyr)
x %>%
   rowwise %>%
   filter(all(c(-1, 1)  %in% sign(c_across(everything())) )) %>%
   ungroup
# A tibble: 2 x 3
#  contrast_1 contrast_2 contrast_3
#       <dbl>      <dbl>      <dbl>
#1        1.3       2.3       -4.5 
#2       -1.2       0.02      -0.24
  

Или используя base R

 subset(x,  (rowSums(sign(x) < 0) > 0) amp; (rowSums(sign(x) > 0) > 0))
#       contrast_1 contrast_2 contrast_3
#gene_2        1.3       2.30      -4.50
#gene_4       -1.2       0.02      -0.24
  

Комментарии:

1. Большое спасибо! Мне очень нравится base R решение: простое, но эффективное.