Определите столбцы, которые имеют только 0 значений

#r

Вопрос:

Я хотел бы получить некоторую помощь со следующим вопросом:

Как вы можете видеть в исполняемом коде ниже, он генерирует график с точками и линией. Эти точки генерируются из моего df1 набора данных. Но обратите внимание, что есть некоторые DR, которые равны только 0, например, DR09, DR10 и DR12. Поэтому я хотел бы выполнить какую-нибудь функцию или что-то такое, что идентифицировало бы, когда все DR равны 0, и это не учитывалось при вычислении моей datas переменной, потому что в этом случае учитывается весь df1 набор данных.

Большое спасибо!

 library(dplyr)
library(lubridate)
library(tidyverse)

df1 <- structure(
  list(date1 = c("2021-06-28","2021-06-28","2021-06-28","2021-06-28","2021-06-28",
                 "2021-06-28","2021-06-28","2021-06-28"),
       date2 = c("2021-04-02","2021-04-03","2021-04-08","2021-04-09","2021-04-10","2021-07-01","2021-07-02","2021-07-03"),
       Week= c("Friday","Saturday","Thursday","Friday","Saturday","Thursday","Friday","Monday"),
       DR01 = c(4,1,4,3,3,4,3,6), DR02= c(4,2,6,7,3,2,7,4),DR03= c(9,5,4,3,3,2,1,5),
       DR04 = c(5,4,3,3,6,2,1,9),DR05 = c(5,4,5,3,6,2,1,9),
       DR06 = c(2,4,3,3,5,6,7,8),DR07 = c(2,5,4,4,9,4,7,8),
       DR08 = c(0,0,0,1,2,0,0,0),DR09 = c(0,0,0,0,0,0,0,0),DR010 = c(0,0,0,0,0,0,0,0),DR011 = c(0,4,0,0,0,0,0,0), DR012 = c(0,0,0,0,0,0,0,0)),
  class = "data.frame", row.names = c(NA, -8L))

#Generate graph

dmda<-"2021-07-01"

datas<-df1 %>%
  filter(date2 == ymd(dmda)) %>%
  summarize(across(starts_with("DR"), sum)) %>%
  pivot_longer(everything(), names_pattern = "DR(. )", values_to = "val") %>%
  mutate(name = as.numeric(name))
colnames(datas)<-c("Days","Numbers")

attach(datas)
plot(Numbers ~ Days, ylim=c(0,20))

model <- nls(Numbers ~ b1*Days^2 b2,start = list(b1 = 47,b2 = 0))

new.data <- data.frame(Days = seq(min(Days),max(Days),len = 45))
lines(new.data$Days,predict(model,newdata = new.data))
 

введите описание изображения здесь

Ответ №1:

Мы можем сделать это с select помощью, т. е. проверить, является ли столбец числовым ( is.numeric ), а where all значения равны 0

 library(dplyr)
df1 %>%
    select(where(~ is.numeric(.) amp;amp; all(. == 0))) %>% 
    names
[1] "DR09"  "DR010" "DR012"
 

Если мы хотим выбрать столбцы, которые их не включают, затем отрицать ( ! )

 df1 %>%
    select(!where(~ is.numeric(.) amp;amp; all(. == 0)))
        date1      date2     Week DR01 DR02 DR03 DR04 DR05 DR06 DR07 DR08 DR011
1 2021-06-28 2021-04-02   Friday    4    4    9    5    5    2    2    0     0
2 2021-06-28 2021-04-03 Saturday    1    2    5    4    4    4    5    0     4
3 2021-06-28 2021-04-08 Thursday    4    6    4    3    5    3    4    0     0
4 2021-06-28 2021-04-09   Friday    3    7    3    3    3    3    4    1     0
5 2021-06-28 2021-04-10 Saturday    3    3    3    6    6    5    9    2     0
6 2021-06-28 2021-07-01 Thursday    4    2    2    2    2    6    4    0     0
7 2021-06-28 2021-07-02   Friday    3    7    1    1    1    7    7    0     0
8 2021-06-28 2021-07-03   Monday    6    4    5    9    9    8    8    0     0
 

Или в base R

 names(which(sapply(df1, function(x) is.numeric(x) amp;amp; all(x == 0))))
[1] "DR09"  "DR010" "DR012"
 

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

1. Идеальный акрун, только одно: если я хочу выбрать из столбца Неделя те DR, в которых нет 0, как мне это сделать? До того, как я сделал что-то подобное: select(Week:DR11)

2. @JSouza Это то обновление в моем посте, которое вы хотели df1 %>% select(!where(~ is.numeric(.) amp;amp; all(. == 0)))

3. @JSouza я имел в виду, что в первом блоке он просто соответствует столбцам, в которых все 0, и выберите его. Во втором случае просто отмените ( ! ), чтобы были выбраны остальные столбцы

Ответ №2:

Мы могли бы использовать colSums :

 df1[, colSums(df1 != 0) > 0]
 

выход:

        date1      date2     Week DR01 DR02 DR03 DR04 DR05 DR06 DR07 DR08 DR011
1 2021-06-28 2021-04-02   Friday    4    4    9    5    5    2    2    0     0
2 2021-06-28 2021-04-03 Saturday    1    2    5    4    4    4    5    0     4
3 2021-06-28 2021-04-08 Thursday    4    6    4    3    5    3    4    0     0
4 2021-06-28 2021-04-09   Friday    3    7    3    3    3    3    4    1     0
5 2021-06-28 2021-04-10 Saturday    3    3    3    6    6    5    9    2     0
6 2021-06-28 2021-07-01 Thursday    4    2    2    2    2    6    4    0     0
7 2021-06-28 2021-07-02   Friday    3    7    1    1    1    7    7    0     0
8 2021-06-28 2021-07-03   Monday    6    4    5    9    9    8    8    0     0
 

Ответ №3:

Мы можем использовать Filter с any

 Filter(function(x) any(x != 0), df1)

#       date1      date2     Week DR01 DR02 DR03 DR04 DR05 DR06 DR07 DR08 DR011
#1 2021-06-28 2021-04-02   Friday    4    4    9    5    5    2    2    0     0
#2 2021-06-28 2021-04-03 Saturday    1    2    5    4    4    4    5    0     4
#3 2021-06-28 2021-04-08 Thursday    4    6    4    3    5    3    4    0     0
#4 2021-06-28 2021-04-09   Friday    3    7    3    3    3    3    4    1     0
#5 2021-06-28 2021-04-10 Saturday    3    3    3    6    6    5    9    2     0
#6 2021-06-28 2021-07-01 Thursday    4    2    2    2    2    6    4    0     0
#7 2021-06-28 2021-07-02   Friday    3    7    1    1    1    7    7    0     0
#8 2021-06-28 2021-07-03   Monday    6    4    5    9    9    8    8    0     0
 

Аналогичная логика также может быть реализована с использованием keep и discard функционированием внутри purrr .

 purrr::keep(df1, ~any(.x != 0))
purrr::discard(df1, ~all(.x == 0))