подсчитать количество столбцов для каждой строки по условию символа и отсутствию

Я хочу подсчитать количество столбцов для каждой строки по условию символа и отсутствию.

Например, у меня есть этот набор данных test.

Я хочу создать num столбца, подсчитывая количество столбцов «не» в отсутствующем или пустом значении.

a<-c("aa","bb","cc","dd","",NA)
b<-c("",NA,"aa","","","dd")
c<-c("aa","",NA,NA,"cc","dd")
d<-c("aa","bb","",NA,"cc","dd")
test<-data.frame(cbind(a,b,c,d))

     a    b    c    d
1   aa        aa   aa
2   bb <NA>        bb
3   cc   aa <NA>     
4   dd      <NA> <NA>
5             cc   cc
6 <NA>   dd   dd   dd

Я хочу подсчитать количество столбцов, содержащих NA и пустое значение, например

     a    b    c    d   num
1   aa        aa   aa   3
2   bb <NA>        bb   2
3   cc   aa <NA>        2
4   dd      <NA> <NA>   1
5             cc   cc   2
6 <NA>   dd   dd   dd   3

Я пробовал какой-то подход в других сообщениях, например rowSums

Подсчитать количество столбцов по условию (›) для каждого строка

> test$num<-rowSums(test!=c("",NA),na.rm=T)
> test
     a    b    c    d num
1   aa        aa   aa   3
2   bb <NA>        bb   0
3   cc   aa <NA>        2
4   dd      <NA> <NA>   0
5             cc   cc   2
6 <NA>   dd   dd   dd   0

Однако он возвращает неправильные числа, и я не мог найти причины.

Не могли бы вы сообщить мне, как решить эту проблему?


person ESKim    schedule 07.02.2020    source источник


Ответы (4)


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

test$num <- ncol(test) - rowSums(is.na(test) | test == "")
test
#     a    b    c    d num
#1   aa        aa   aa   3
#2   bb <NA>        bb   2
#3   cc   aa <NA>        2
#4   dd      <NA> <NA>   1
#5             cc   cc   2
#6 <NA>   dd   dd   dd   3
person Ronak Shah    schedule 07.02.2020
comment
Мой ответ был удален, так как он был слишком близок к вашему: rowSums(test != "" & !is.na(test)) - person sindri_baldur; 07.02.2020
comment
@sindri_baldur Я думаю, что это достаточно другой ответ, чтобы быть отдельным ответом. - person Ronak Shah; 07.02.2020

Другая идея использования rowSums - заменить пустое значение на NA, т.е.

rowSums(!is.na(replace(test, test == '', NA)))
#[1] 3 2 2 1 2 3
person Sotos    schedule 07.02.2020

Вы можете использовать nchar + rowSums

test$num <- rowSums(nchar(as.matrix(test))>1,na.rm = TRUE)

or %in% + rowSums

test$num <- rowSums(`dim<-`(!as.matrix(test) %in% c("",NA),dim(test)))

такой, что

> test
     a    b    c    d num
1   aa        aa   aa   3
2   bb <NA>        bb   2
3   cc   aa <NA>        2
4   dd      <NA> <NA>   1
5             cc   cc   2
6 <NA>   dd   dd   dd   3
person ThomasIsCoding    schedule 07.02.2020

Как насчет этого подхода из tidyverse, который также сообщает вам, сколько столбцов содержат NA или пустые строки?

a<-c("aa","bb","cc","dd","",NA)
b<-c("",NA,"aa","","","dd")
c<-c("aa","",NA,NA,"cc","dd")
d<-c("aa","bb","",NA,"cc","dd")
test<-data.frame(cbind(a,b,c,d))

library(magrittr) #import the pipe operator

num_cols <- test %>% 
    tibble::rowid_to_column("row_id") %>% #1st add a rowid column 
    dplyr::group_by(row_id) %>% #split the data into single row groups (i.e. 
                                #row vectors)
    tidyr::nest() %>% #turn it into a list column called data
    dplyr::mutate(num_NAs = purrr::map_dbl(data, #loop over the data column of row 
                                                  #vectors using map_dbl
                                     ~sum(is.na(.))), #count the number of NAs
                  num_empty = purrr::map_dbl(data, 
                                         #count the empty strings 
                                         ~sum(. == "", na.rm = T)),
                  num_values = purrr::map_dbl(data, 
                                          #count columns without NAs or 
                                          #missing values (what you asked for)
                                          ~length(.)-sum(num_NAs, num_empty))
            ) %>%
    dplyr::ungroup() %>% #remove the grouping structure
    dplyr::select(num_NAs, num_empty, num_values) #extract only the variables you need

test_v2 <- cbind(test, num_cols)
test_v2  

     a    b    c    d num_NAs num_empty num_values
1   aa        aa   aa       0         1          3
2   bb <NA>        bb       1         1          2
3   cc   aa <NA>            1         1          2
4   dd      <NA> <NA>       2         1          1
5             cc   cc       0         2          2
6 <NA>   dd   dd   dd       1         0          3
person huttoncp    schedule 07.02.2020
comment
Хотя для этого решения требуется больше кода, чем для других вариантов, оно дает вам больше информации (если она вам нужна). Вы также можете легко вставить слой select () в начале (перед слоем group_by), чтобы применить эти правила подсчета только к подмножеству столбцов, если вы не хотите получать подсчеты для всего фрейма данных. - person huttoncp; 08.02.2020