Как проверить, содержит ли R dataframe только 1 или 0

#r #dataframe

#r #dataframe

Вопрос:

Мне интересно, какой наиболее эффективный способ проверить, содержит ли фрейм погодных данных только 1 или 0 или нет. Я бы сказал, что мне пришла в голову очень интуитивная, но неэффективная идея.

Моя идея

Заключается в преобразовании всего фрейма данных в вектор. Затем проверьте, равна ли длина этого вектора сумме длин всех столбцов с условиями == 0 или ==1.

Пример

 > df<-data.frame(sample(0:1,10,replace=T),sample(0:1,10,replace=T),sample(0:1,10,replace=T))
> df
   sample.0.1..10..replace...T. sample.0.1..10..replace...T..1 sample.0.1..10..replace...T..2
1                             0                              1                              1
2                             0                              0                              1
3                             1                              1                              0
4                             0                              0                              0
5                             1                              0                              1
6                             0                              0                              0
7                             1                              0                              0
8                             0                              0                              0
9                             0                              1                              0
10                            1                              0                              1



 length(unlist(df,use.names=F))
 30
 length(df[,1][df[,1]==0]) length(df[,1][df[,1]==1]) length(df[,2][df[,2]==0]) length(df[,2] 
 [df[,2]==1]) length(df[,3][df[,3]==0]) length(df[,3][df[,3]==1])
 30
  

Есть ли более быстрый способ, как это сделать?

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

1. Почему это data.frame, а не матрица? Вы могли бы просто сделать all(as.matrix(df) %in% 0:1) . (Я предполагаю, что значения данных были импортированы и не являются вычисляемыми числами с плавающей запятой.)

2. all(unlist(df) %in% c(0, 1)) а all(df == 0 | df == 1) также работает.

Ответ №1:

Обычно я бы пошел на

 all(sapply(df, function(x) all(x) %in% c(0,1)))
[1] TRUE
  

Однако вы должны знать, что R принудительно преобразует логические значения в числовые при оценке этих условий. Это может привести к возврату TRUE даже для логических значений. Например, предыдущий оператор возвращает TRUE для

 test <- c(TRUE, TRUE, FALSE)
  

Поэтому это решение необходимо изменить, чтобы проверить числовые значения, которые вам нужны.

 all(sapply(test, function(x) is.numeric(x) amp; all(x) %in% c(0,1)))
[1] FALSE
all(sapply(df, function(x) is.numeric(x) amp; all(x) %in% c(0,1)))
[1] TRUE
  

РЕДАКТИРОВАТЬ: он также работает с данными, которые включают NA ‘s, с предупреждением.

 df_missing <- df
df_missing$nacol <- c(rep(1,9),NA)
all(sapply(df_missing, function(x) is.numeric(x) amp; all(x) %in% c(0,1)))
[1] FALSE
Warning message:
In all(x) : coercing argument of type 'double' to logical
  

Ответ №2:

Вы могли бы перейти к table функции и проверить, есть ли all names %in% 0:1 они. Если вы хотите учесть пропущенный аргумент use use.na= , опустите его в противном случае.

Вот как это выглядит:

 table(unlist(dat.m), useNA="ifany")
#  0    1 <NA> 
# 52   73   10 
  

В действии:

 all(names(table(unlist(dat), useNA="ifany")) %in% 0:1)
# [1] TRUE
all(names(table(unlist(dat.m), useNA="ifany")) %in% 0:1)
# [1] FALSE
all(names(table(unlist(dat.99), useNA="ifany")) %in% 0:1)
# [1] FALSE
  

Данные:

 m <- 15;n <- 9
set.seed(42)
M <- matrix(rbinom(m*n, 1, .5), m, n)

## clean
dat <- as.data.frame(M)

## with missings
M[as.logical(rbinom(length(M), 1, .1))] <- NA
dat.na <- as.data.frame(M)

## with other numbers
M[as.logical(rbinom(length(M), 1, .1))] <- -99
dat.99 <- as.data.frame(M)