Вычислить rowMeans для диапазона столбца (номер переменной)

Я хочу вычислить rowMeans диапазона столбца, но не могу дать жестко запрограммированное значение для имен столбцов (например, c(C1,C3)) или диапазона (например, C1:C3), так как имена и диапазон являются переменными. Мой DF выглядит так:

> df
  chr name age  MGW.1 MGW.2  MGW.3 HEL.1 HEL.2 HEL.3
1 123  abc  12  10.00    19  18.00    12 13.00   -14
2 234  bvf  24 -13.29    13  -3.02    12 -0.12    24
3 376  bxc  17  -6.95    10 -18.00    15  4.00    -4

Это всего лишь пример, на самом деле у меня есть столбцы в MGW.1 ... MGW.196 и так далее. Здесь Вместо того, чтобы давать точные имена столбцов или точный диапазон, я хочу передать начальные значения имен столбцов и получить среднее значение для всех столбцов, имеющих эти инициалы. Что-то вроде: MGW=rowMeans(df[,MGW.*]), HEL=rowMeans(df[,HEL.*])

Итак, мой окончательный вывод должен выглядеть так:

> df
      chr name age  MGW      Hel
    1 123  abc  12  10.00    19
    2 234  bvf  24  13.29    13
    3 376  bxc  17  -6.95    10

Я знаю, что эти значения не верны, но это просто дать вам и идею. Во-вторых, я хочу удалить все эти строки из фрейма данных, который содержит NA во всей строке, кроме первых 3-х значений.

Вот dput для примера:

> dput(df)
structure(list(chr = c(123L, 234L, 376L), name = structure(1:3, .Label = c("abc", 
"bvf", "bxc"), class = "factor"), age = c(12L, 24L, 17L), MGW.1 = c(10, 
-13.29, -6.95), MGW.2 = c(19L, 13L, 10L), MGW.3 = c(18, -3.02, 
-18), HEL.1 = c(12L, 12L, 15L), HEL.2 = c(13, -0.12, 4), HEL.3 = c(-14L, 
24L, -4L)), .Names = c("chr", "name", "age", "MGW.1", "MGW.2", 
"MGW.3", "HEL.1", "HEL.2", "HEL.3"), class = "data.frame", row.names = c(NA, 
-3L))

2 ответа

Решение

Вот идея достижения желаемого результата без жесткого кодирования имен переменных:

library(dplyr)
library(tidyr)

df %>%
  # remove rows where all values are NA except the first 3 columns
  filter(rowSums(is.na(.[4:length(.)])) != length(.) - 3) %>%
  # gather the data in a tidy format
  gather(key, value, -(chr:age)) %>%
  # separate the key column into label and num allowing 
  # to regroup by variables without hardcoding them
  separate(key, into = c("label", "num")) %>%
  group_by(chr, name, age, label) %>%
  # calculate the mean
  summarise(mean = mean(value, na.rm = TRUE)) %>%
  spread(label, mean)

Я позволил себе изменить ваши исходные данные, чтобы показать, как логика будет соответствовать особым случаям. Например, здесь у нас есть строка (#4), где все значения, кроме первых 3 столбцов NAs (в соответствии с вашими требованиями, этот ряд должен быть удален) и один, где есть сочетание NAс и значения (#5). В этом случае я предположил, что мы хотели бы получить результат для MGW так как есть значение в MGW.1:

#  chr name age  MGW.1 MGW.2  MGW.3 HEL.1 HEL.2 HEL.3
#1 123  abc  12  10.00    19  18.00    12 13.00   -14
#2 234  bvf  24 -13.29    13  -3.02    12 -0.12    24
#3 376  bxc  17  -6.95    10 -18.00    15  4.00    -4
#4 999  zzz  21     NA    NA     NA    NA    NA    NA
#5 888  aaa  12  10.00    NA     NA    NA    NA    NA

Который дает:

#Source: local data frame [4 x 5]
#Groups: chr, name, age [4]
#
#    chr   name   age       HEL       MGW
#* <int> <fctr> <int>     <dbl>     <dbl>
#1   123    abc    12  3.666667 15.666667
#2   234    bvf    24 11.960000 -1.103333
#3   376    bxc    17  5.000000 -4.983333
#4   888    aaa    12       NaN 10.000000

Данные

df <- structure(list(chr = c(123L, 234L, 376L, 999L, 888L), name = structure(c(2L, 
3L, 4L, 5L, 1L), .Label = c("aaa", "abc", "bvf", "bxc", "zzz"
), class = "factor"), age = c(12L, 24L, 17L, 21L, 12L), MGW.1 = c(10, 
-13.29, -6.95, NA, 10), MGW.2 = c(19L, 13L, 10L, NA, NA), MGW.3 = c(18, 
-3.02, -18, NA, NA), HEL.1 = c(12L, 12L, 15L, NA, NA), HEL.2 = c(13, 
-0.12, 4, NA, NA), HEL.3 = c(-14L, 24L, -4L, NA, NA)), .Names = c("chr", 
"name", "age", "MGW.1", "MGW.2", "MGW.3", "HEL.1", "HEL.2", "HEL.3"
), class = "data.frame", row.names = c("1", "2", "3", "4", "5"))

во-первых

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

df$mean.Hel <- rowMeans(df[, grep("^HEL.", names(df))])

И чтобы впоследствии удалить столбцы:

df[, grep("^HEL.", names(df))] <- NULL

во-вторых

Удалить строки, которые имеют только NA после первых трех элементов.

rows.delete <- which(rowSums(!is.na(df)[,4:ncol(df)]) == 0)
df <- df[!(1:nrow(df) %in% rows.delete),]
Другие вопросы по тегам