Как удалить строки с любым нулевым значением

У меня есть проблема, чтобы решить, как удалить строки с нулевым значением в R. С другой стороны, я могу использовать na.omit() для удаления всех значений NA или использовать complete.cases() для удаления строк, содержащих значения NA.

Кто-нибудь знает, как удалить строки с нулевыми значениями в R?

Например :

До

|    DateTime      | Mac1  | Mac2  | Mac3  | Mac4  |
----------------------------------------------------
| 2011-04-02 06:00 | 20    | 0     | 20    | 20    |  
| 2011-04-02 06:05 | 21    | 21    | 21    | 21    |  
| 2011-04-02 06:10 | 22    | 22    | 22    | 22    |  
| 2011-04-02 06:15 | 23    | 23    | 0     | 23    |  
| 2011-04-02 06:20 | 24    | 24    | 24    | 24    | 
| 2011-04-02 06:25 | 0     | 25    | 25    | 0     | 

После

|    DateTime      | Mac1  | Mac2  | Mac3  | Mac4  |
----------------------------------------------------
| 2011-04-02 06:05 | 21    | 21    | 21    | 21    |  
| 2011-04-02 06:10 | 22    | 22    | 22    | 22    |  
| 2011-04-02 06:20 | 24    | 24    | 24    | 24    |  

person YougyZ    schedule 02.04.2012    source источник
comment
Один путь: свести это к проблеме, которую вы уже решили, заменив нули на NA.   -  person joran    schedule 02.04.2012
comment
Спасибо, Джоран, за ответ .. Но, я не понимаю, что означает замена нулей на NA? Потому что, прежде чем я получу таблицу, я уже удалил значения NA. Но значения 0 по-прежнему остаются. Подскажите, как это сделать?   -  person YougyZ    schedule 02.04.2012
comment
Хорошо, я думаю, мне нужно использовать этот код, чтобы заменить 0 на NAs .. data[which(data==0)] = NA   -  person YougyZ    schedule 02.04.2012
comment
@YougyZ Думаю, тебе понадобится data[which(data==0)] = NA_character_   -  person DaveRGP    schedule 16.01.2015


Ответы (9)


Есть несколько способов сделать это. Я предпочитаю использовать apply, так как его легко расширить:

##Generate some data
dd = data.frame(a = 1:4, b= 1:0, c=0:3)

##Go through each row and determine if a value is zero
row_sub = apply(dd, 1, function(row) all(row !=0 ))
##Subset as usual
dd[row_sub,]
person csgillespie    schedule 02.04.2012

Я бы, вероятно, согласился с предложением Джорана заменить 0 на NA, а затем использовать встроенные функции, о которых вы упомянули. Если вы не можете / не хотите этого делать, можно использовать any() для поиска строк, содержащих 0, и их подмножества:

set.seed(42)
#Fake data
x <- data.frame(a = sample(0:2, 5, TRUE), b = sample(0:2, 5, TRUE))
> x
  a b
1 2 1
2 2 2
3 0 0
4 2 1
5 1 2
#Subset out any rows with a 0 in them
#Note the negation with ! around the apply function
x[!(apply(x, 1, function(y) any(y == 0))),]
  a b
1 2 1
2 2 2
4 2 1
5 1 2

Чтобы реализовать метод Джорана, вы должны начать примерно так:

x[x==0] <- NA
person Chase    schedule 02.04.2012
comment
в любом случае спасибо, но я сделал это с помощью решения csgillespie ..;) - person YougyZ; 02.04.2012

Что ж, вы можете поменять свои 0 на NA, а затем использовать одно из этих решений, но для разницы вы могли заметить, что число будет иметь конечный логарифм, только если оно больше 0, так что rowSums из log будет быть конечным только в том случае, если в ряду нет нулей.

dfr[is.finite(rowSums(log(dfr[-1]))),]
person James    schedule 02.04.2012
comment
+1 за умных, но на практике я бы предпочел _1 _ / _ 2_ решение ... - person Ben Bolker; 02.04.2012

Я бы сделал следующее.

Установите ноль на NA.

 data[data==0] <- NA
 data

Удалите строки, связанные с NA.

 data2<-data[complete.cases(data),]
person morteza    schedule 14.05.2018

Я предпочитаю простую адаптацию метода csgillespie, отказавшись от необходимости определения функции:

d[apply(d!=0, 1, all),]

где d - ваш фрейм данных.

person Robert Yi    schedule 20.12.2017
comment
У меня это не работает, но работает: d [! Apply (d == 0, 1, all),] - person Sandipan Dey; 24.07.2018

Вы можете использовать фильтр из пакета dplyr.

Назовем ваш фрейм данных df

library(dplyr) df1 <- filter(df, Mac1 > 0, Mac2 > 0, Mac3 > 0, Mac4 > 0)

df1 будет иметь только строки с записями больше нуля. Надеюсь это поможет.

person Vinay B    schedule 10.10.2018

Используя tidyverse / dplyr, вы также можете удалить строки с любым нулевым значением в подмножестве переменных:

# variables starting with Mac must be non-zero
filter_at(df, vars(starts_with("Mac")), all_vars((.) != 0))

# variables x, y, and z must be non-zero
filter_at(df, vars(x, y, z), all_vars((.) != 0))

# all numeric variables must be non-zero
filter_if(df, is.numeric, all_vars((.) != 0))
person Feng Mai    schedule 13.12.2019

В базе R мы можем выбрать столбцы, которые мы хотим протестировать, используя grep, сравнить данные с 0, использовать rowSums для выбора строк, которые имеют все ненулевые значения.

cols <- grep("^Mac", names(df))
df[rowSums(df[cols] != 0) == length(cols), ]

#          DateTime Mac1 Mac2 Mac3 Mac4
#1 2011-04-02 06:05   21   21   21   21
#2 2011-04-02 06:10   22   22   22   22
#3 2011-04-02 06:20   24   24   24   24

Делая это с перевернутой логикой, но давая тот же результат

df[rowSums(df[cols] == 0) == 0, ]

В dplyr мы можем использовать filter_at для проверки определенных столбцов и использовать all_vars для выбора строк, все значения которых не равны 0.

library(dplyr)
df %>%  filter_at(vars(starts_with("Mac")), all_vars(. != 0))

данные

df <- structure(list(DateTime = structure(1:6, .Label = c("2011-04-02 06:00", 
"2011-04-02 06:05", "2011-04-02 06:10", "2011-04-02 06:15", "2011-04-02 06:20", 
"2011-04-02 06:25"), class = "factor"), Mac1 = c(20L, 21L, 22L, 
23L, 24L, 0L), Mac2 = c(0L, 21L, 22L, 23L, 24L, 25L), Mac3 = c(20L, 
21L, 22L, 0L, 24L, 25L), Mac4 = c(20L, 21L, 22L, 23L, 24L, 0L
)), class = "data.frame", row.names = c(NA, -6L))
person Ronak Shah    schedule 13.09.2019

Поскольку dplyr 1.0.0 не рекомендовал варианты с ограниченной областью видимости, которые прекрасно показал @Feng Mai, вот обновление с новым синтаксисом. Это может быть полезно, потому что в данном случае across() не работает, и мне потребовалось некоторое время, чтобы найти решение, как показано ниже.

Целью было извлечь все строки, содержащие хотя бы один 0 в столбце.

df %>% 
  rowwise() %>% 
  filter(any(c_across(everything(.)) == 0))

с данными

df <- data.frame(a = 1:4, b= 1:0, c=0:3)
df <- rbind(df, c(0,0,0))
df <- rbind(df, c(9,9,9))

# A tibble: 4 x 3
# Rowwise: 
      a     b     c
  <dbl> <dbl> <dbl>
1     1     1     0
2     2     0     1
3     4     0     3
4     0     0     0

Таким образом, он правильно не возвращает последнюю строку, содержащую все 9.

person Agile Bean    schedule 08.01.2021