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

#r

#r

Вопрос:

Я хотел бы рассчитать «интервал значений, отличных от NA», для разных столбцов.

Вот набор данных:

 temp <- data.frame(
  date = seq(as.Date("2018-01-01"), by = 'month', length.out = 12),
  X1 = c(100, NA, 23, NA, NA, 12, NA, NA, NA, NA, NA, 100),
  X2 = runif(12, 50, 100),
  X3 = c(24, NA, NA, NA, NA, 31, 1, NA, 44, NA, 100, NA),
  X4 = NA
)
 

Например, X1 имеет интервалы, отличные от NA, как 1, 2, 5 , что означает, что от 100 до 23 между этими двумя значениями, отличными от NA, находится 1 NA, от 23 до 12 между этими двумя значениями, отличными от NA, есть 2 NAs, а от 12 до 100 между этими двумя значениями 5 NAsзначения, отличные от NA.

Ожидаемый результат:

 result <- data.frame(
  X1_inv_mean = mean(c(1, 2, 5)),
  X1_inv_median = median(c(1, 2, 5)),
  X1_inv_sd = sd(c(1, 2, 5)),

  X2_inv_mean = mean(0),
  X2_inv_median = median(0),
  X2_inv_sd = sd(0),

  X3_inv_mean = mean(c(4, 1, 1, 1)),
  X3_inv_median = median(c(4, 1, 1, 1)),
  X3_inv_sd = sd(c(4, 1, 1, 1)),

  X4_inv_mean = NA,
  X4_inv_median = NA,
  X4_inv_sd = NA
)

>result
  X1_inv_mean X1_inv_median X1_inv_sd X2_inv_mean X2_inv_median X2_inv_sd X3_inv_mean X3_inv_median X3_inv_sd
1    2.666667             2  2.081666           0             0        NA        1.75             1       1.5
  X4_inv_mean X4_inv_median X4_inv_sd
1          NA            NA        NA
 

Спасибо за помощь!

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

1. Результат не обязательно точно такой же, как в сообщении, просто с аналогичным результатом будет оценен по достоинству.

2. X1 имеет интервалы, отличные от NA, как 1, 2, 5 … почему?? Что вы подразумеваете под интервалами, отличными от NA ?

3. Обратите внимание, что X4 существует 12 последовательных NA секунд, и поэтому ваш желаемый результат неверен (при условии, что я правильно вас понял).

4. @Sotos, я обновил сообщение, так что, надеюсь, я лучше объяснил это вам.

5. @markus Для X4 да, я ожидаю, что это будет NA для столбца ALL-NA.

Ответ №1:

Базовый параметр R

 out <- lapply(temp[-1], function(x) {
  if(all(is.na(x))) {
    tmp <- NA
  } else {
    tmp <- with(rle(is.na(x)), lengths[values])
    c(mean = mean(tmp),
      median = median(tmp),
      sd = sd(tmp))}
  })

as.data.frame(out)
#             X1  X2   X3 X4
#mean   2.666667 NaN 1.75 NA
#median 2.000000  NA 1.00 NA
#sd     2.081666  NA 1.50 NA
 

Использование rle следующей строки дает вам значения NA s для каждого столбца

 tmp <- with(rle(is.na(x)), lengths[values])
 

Например, для столбца X1

 with(rle(is.na(temp$X1)), lengths[values])
#[1] 1 2 5
 

Затем мы вычисляем вашу итоговую статистику для каждого tmp .

Если все значения в столбце NA равны, функция возвращает NA .

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

1. Я получаю результат для исходного набора данных. Ответ идеальный! Здесь у меня есть дополнительный вопрос, что означает это lengths[values] ? Я понимаю with() , и его аргументы, кроме того, результат rle дает список, содержащий lengths и values , но я не могу связать результат rle с этим lengths[values] . Спасибо!

2. @J.D Как вы заметили, rle() возвращает объект с двумя компонентами: lengths и values . В приведенном выше примере последний является логическим вектором. Использование with позволяет оценивать эти компоненты в локальной среде. То есть нам не нужно сначала присваивать результат rle имени, а затем манипулировать его значениями, мы можем сделать это за один раз. Поскольку values имеет логический тип, что lengths[values] возвращает только те значения lengths , для которых values есть TRUE . То же r <- rle(is.na(temp$X1)); r$lengths[r$values] самое, что и — просто приятнее читать для интерактивного использования.

Ответ №2:

Обновление: для переменных n столбцов:

 command <- ""
summaryString <- ""
for(i in colnames(temp)){
     if(i != "date"){
       print(i)
       summaryString <- paste(summaryString,i,"_inv_mean = mean(",i,", na.rm = T),",sep="")
       summaryString <- paste(summaryString,i,"_inv_median = median(",i,", na.rm = T),",sep="")
       summaryString <- paste(summaryString,i,"_inv_sd = sd(",i,", na.rm = T),",sep="")
     }

   command <- paste("output <- temp %>% summarise(",substr(summaryString, 0, nchar(summaryString)-1),")",sep="")
}

eval(parse(text=command))
 

Использование dplyr:

 library(dplyr)
output <- temp%>%
  summarise(x1_inv_mean = mean(X1, na.rm = T),
        x1_inv_median = median(X1, na.rm = T),
        x1_inv_sd = sd(X1, na.rm = T),
        x2_inv_mean = median(X2, na.rm = T),
        x2_inv_median = mean(X2, na.rm = T),
        x2_inv_sd = sd(X2, na.rm = T),
        x3_inv_mean = median(X3, na.rm = T),
        x3_inv_median = mean(X3, na.rm = T),
        x3_inv_sd = sd(X3, na.rm = T),
        x4_inv_mean = mean(X4, na.rm = T),
        x4_inv_median = median(X4, na.rm = T),
        x4_inv_sd = sd(X4, na.rm = T))