Средние значения строк подмножества столбцов на основе (исключенного) значения соответствующего столбца в R - PullRequest
2 голосов
/ 05 мая 2020

Я ищу более аккуратное решение для создания столбца средств строки для выбора столбцов в моих данных на основе условия соответствующего значения столбца. Я создал несколько фиктивных данных, чтобы показать, что я имею в виду. Каждая строка представляет собой группу ответов, каждая из которых пронумерована A и B - переменные из одного и того же ответа в группе. Я хочу найти среднее значение значений A для каждой строки, но только тех, которые соответствуют критерию их соответствующего значения B (например,> 17).

df = data.frame(
  A1 = c(15,15,1,5,8),
  A2 = c(10,NA,5,3,10),
  A3 = c(NA,NA,6,4,10),
  A4 = c(NA,NA,5,5,NA),
  B1 = c(55,40,29,33,42),
  B2 = c(29,NA,18,11,26),
  B3 = c(NA,NA,14,8,22),
  B4 = c(NA,NA,11,16,NA))

> df
  A1 A2 A3 A4 B1 B2 B3 B4
1 15 10 NA NA 55 29 NA NA
2 15 NA NA NA 40 NA NA NA
3  1  5  6  5 29 18 14 11
4  5  3  4  5 33 11  8 16
5  8 10 10 NA 42 26 22 NA

Так ищу что-то вроде этого.

    mean
1 12.500
2 15.000
3  3.000
4  5.000
5  9.333

Решение, которое у меня есть до сих пор, - создать новый столбец, реплицирующий все значения A, которые я хочу включить, а затем выполнить rowMeans для этих столбцов:

for (i in 1:4){
  A_inc = ifelse(df[,paste('B',i,sep='')] >= 17, df[,paste('A',i,sep='')],
                NA)
  df[, paste0('A_inc',i,sep = '')] <- A_inc
}

df$mean = rowMeans(df[grep('A_inc', names(df))], na.rm=TRUE)

> df
  A1 A2 A3 A4 B1 B2 B3 B4 A_inc1 A_inc2 A_inc3 A_inc4      mean
1 15 10 NA NA 55 29 NA NA     15     10     NA     NA 12.500000
2 15 NA NA NA 40 NA NA NA     15     NA     NA     NA 15.000000
3  1  5  6  5 29 18 14 11      1      5     NA     NA  3.000000
4  5  3  4  5 33 11  8 16      5     NA     NA     NA  5.000000
5  8 10 10  0 42 26 22  3      8     10     10     NA  9.333333

Это работает, но это неудобно для моего гораздо большего набора данных и с более сложными условиями из большего количества столбцов (B, C, D и других). Я знаю, что должен быть лучший способ сделать это, и надеялся получить какие-то лучшие методы.

Ответы [ 2 ]

1 голос
/ 05 мая 2020

Вы можете использовать rowMeans там, где вы перезаписали значения, где !B>17:

x <- df[,startsWith(colnames(df), "A")]
x[!df[,gsub("A", "B", colnames(x))] > 17] <- NA
rowMeans(x, na.rm=TRUE)
#[1] 12.500000 15.000000  3.000000  5.000000  9.333333

Я предполагаю, что есть соответствующий B для каждого A.

0 голосов
/ 05 мая 2020

Чтобы обеспечить большую гибкость, которую вы, кажется, желаете, вам необходимо коренным образом реструктурировать свои данные. Как только вы получите его в легко управляемой форме, вы сможете легко проводить любой анализ, какой захотите. Таким образом, затраты на создание этого набора данных возникают в начале, а затем любая операция обходится относительно дешевле. В частности, вы хотите использовать возможности data.frame в R, и поэтому вам необходимо соответственно расплавить / преобразовать свой набор данных, чтобы каждая строка представляла собой наблюдение groupXid с переменными A и B. Ниже приведен один способ выполнить sh, что, using data.table:

df = data.frame(
  A1 = c(15,15,1,5,8),
  A2 = c(10,NA,5,3,10),
  A3 = c(NA,NA,6,4,10),
  A4 = c(NA,NA,5,5,NA),
  B1 = c(55,40,29,33,42),
  B2 = c(29,NA,18,11,26),
  B3 = c(NA,NA,14,8,22),
  B4 = c(NA,NA,11,16,NA))

setDT(df)

#each group is a row, so define these groups
df[, group := 1:.N]

#melt where idvar is a group
df = melt(df, id.var = "group")

#variables are defined by the first letter you define, easy to adapt this accordingly
df[, vars := substring(variable,1,1)]
#individuals within a group are defined by the number, 
#ie the second character in the column names of your original dataset
df[, id := substring(variable,2)]
df[, variable := NULL]

#now cast so that each row is a groupXid observation, and columns are the variables vars
rdy_dt = dcast(df, group + id ~ vars, value.var = "value")

Итак, у вас есть желаемый набор данных, и теперь вы можете использовать функциональные возможности data.table, чтобы делать все, что захотите. Например, чтобы получить средства, просто выполните

#condition is B >= 17, and we want the mean by group.
rdy_dt[B >= 17, mean(A,na.rm = T), by = group]
   group        V1
1:     1 12.500000
2:     2 15.000000
3:     3  3.000000
4:     4  5.000000
5:     5  9.333333

И вы можете комбинировать любые наборы условий из нескольких переменных как таковые.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...