R- Вычитание среднего значения группы из каждого элемента этой группы в кадре данных. - PullRequest
0 голосов
/ 26 июня 2018

Я пытаюсь объединить вектор 'средства' в фрейм данных. Мой фрейм данных выглядит следующим образом Данные = рост

Сначала я рассчитал все средства для разных групп (1 группа = население + температура + размер + репликация) с помощью этой команды:

means<-aggregate(TL ~ Population + Temperature + Replicat + Size + Measurement, data=growth, list=growth$Name, mean)        

Затем я выбрал средства для измерения 1 следующим образом, поскольку меня интересуют только эти средства.

meansT0<-means[which(means$Measurement=="1"),]    

Теперь я хотел бы объединить этот вектор средних значений с моим фреймом данных (= рост), чтобы правильное среднее значение каждой группы соответствовало правой части фрейма данных.

Цель состоит в том, чтобы затем подставить среднее значение каждой группы (в измерении 1) каждому элементу кадра данных на основе его принадлежащей группы (и для всех других измерений, кроме измерения 1). Может быть, нет необходимости добавлять столбец средств в фрейм данных? Вы знаете какую-нибудь команду, чтобы сделать это?

[27.06.18] Я составил этот упрощенный фрейм данных, надеюсь, это поможет понять. Итак, я хочу, чтобы для каждого отдельного человека в кадре данных и для каждого измерения (здесь только Измерение 1 и Измерение 2, обычно у меня было больше), было получено среднее значение его группы принадлежности в ИЗМЕРЕНИИ 1.

Итак, если я получу средства по группам ( 1 группа = Население + Температура + Измерение):

means<-aggregate(TL ~ Population + Temperature + Measurement, data=growth, list=growth$Name, mean)
means               

Я получил следующие значения средств (в этом примере):

Population Temperature Measurement       TL
JUB          15           **1**           **12.00000**
JUB          20           **1**           **15.66667**
JUB          15           2           17.66667
JUB          20           2           18.66667
JUB          15           3           23.66667
JUB          20           3           24.33333

Нас интересуют только средства в ИЗМЕРЕНИИ 1. Для каждого отдельного лица в кадре данных я хочу подставить среднее значение его принадлежащей группы в Измерении 1: в этом примере (см. Кадр данных с командой R): - для группы JUB + 15 + Измерение 1 , среднее = 12 - для группы JUB + 20 + Измерение 1 , среднее = 15,66

growth<-data.frame(Population=c("JUB", "JUB", "JUB","JUB", "JUB", "JUB","JUB", "JUB", "JUB","JUB", "JUB", "JUB","JUB", "JUB", "JUB","JUB", "JUB", "JUB"), Measurement=c("1","1","1","1","1","1","2","2","2","2","2","2", "3", "3", "3", "3", "3", "3"),Temperature=c("15","15","15","20", "20", "20","15","15","15","20", "20", "20","15","15","15","20", "20", "20"),TL=c(11,12,13,15,18,14, 16,17,20,21,19,16, 25,22,24,26,24,23), New_TL=c("11-12", "12-12", "13-12", "15-15.66", "18-15.66", "14-15.66", "16-12", "17-12", "20-12", "21-15.66", "19-15.66", "16-15.66", "25-12", "22-12", "24-12", "26-15.66", "24-15.66", "23-15.66"))    
print(growth)

Надеюсь, с этим вы сможете лучше понять, что я пытаюсь сделать. У меня много данных, и если мне придется делать это вручную, это займет у меня много времени и увеличит риск ошибок.

Ответы [ 3 ]

0 голосов
/ 26 июня 2018

Рассмотрим by для подстановки вашего фрейма данных с помощью факторов (но не включайте Измерение , чтобы сравнить группу 1 и все другие группы). Затем выполните расчет условной логики ifelse для нужных столбцов. Поскольку by вернет список фреймов данных, свяжите все снаружи с помощью do.call():

df_list <- by(growth, growth[,c("Population", "Temperature")], function(sub) {
  # TL CORRECTION      
  sub$Correct_TL <- ifelse(sub$Measurement != 1, 
                           sub$TL - mean(subset(sub, Measurement == 1)$TL),
                           sub$TL)
  # ADD OTHER CORRECTIONS

  return(sub)  
})

final_df <- do.call(rbind, df_list)

Вывод (с использованием опубликованных данных)

final_df

#    Population Measurement Temperature TL   New_TL Correct_TL
# 1         JUB           1          15 11    11-12 11.0000000
# 2         JUB           1          15 12    12-12 12.0000000
# 3         JUB           1          15 13    13-12 13.0000000
# 7         JUB           2          15 16    16-12  4.0000000
# 8         JUB           2          15 17    17-12  5.0000000
# 9         JUB           2          15 20    20-12  8.0000000
# 13        JUB           3          15 25    25-12 13.0000000
# 14        JUB           3          15 22    22-12 10.0000000
# 15        JUB           3          15 24    24-12 12.0000000
# 4         JUB           1          20 15 15-15.66 15.0000000
# 5         JUB           1          20 18 18-15.66 18.0000000
# 6         JUB           1          20 14 14-15.66 14.0000000
# 10        JUB           2          20 21 21-15.66  5.3333333
# 11        JUB           2          20 19 19-15.66  3.3333333
# 12        JUB           2          20 16 16-15.66  0.3333333
# 16        JUB           3          20 26 26-15.66 10.3333333
# 17        JUB           3          20 24 24-15.66  8.3333333
# 18        JUB           3          20 23 23-15.66  7.3333333
0 голосов
/ 26 июня 2018

Вот вариант с tidyverse. После группировки по столбцам группы используйте mutate_at, указав интересующие столбцы, и получите разницу этого столбца (.) с mean.

library(tidyverse)
growth %>% 
       group_by(Population, Temperature, Replicat, Size, Measurement) %>% 
       mutate_at(vars(HL, TL), funs(MeanGroupDiff = . 
                  - mean(.[Measurement == 1])))

Использование воспроизводимого примера с mtcars набором данных

data(mtcars)
mtcars %>%
   group_by(cyl, vs) %>% 
   mutate_at(vars(mpg, disp), funs(MeanGroupDiff = .- mean(.[am==1])))
0 голосов
/ 26 июня 2018

Рассматривали ли вы использование пакета data.table? Он очень хорошо подходит для выполнения описанных вами операций группировки, фильтрации, объединения и агрегирования и может сэкономить вам много времени в долгосрочной перспективе.

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

Чтобы было ясно, есть также способы сделать то, что вы описываете, используя base R, а также другие пакеты, такие как dplyr, просто выбрасывая предложение на основе того, что я нашел наиболее полезным для моего Личная работа.

library(data.table)

## Convert mtcars to a data.table
## only include columns `mpg`, `cyl`, `am` and `gear` for brevity
DT <- as.data.table(mtcars)[, .(mpg, cyl,am, gear)]

## Take a subset where `cyl` is equal to 6
DT <- DT[cyl == 6]

## Calculate grouped mean based on `gear` and `am` as grouping variables
DT[,group_mpg_avg := mean(mpg), keyby = .(gear, am)]

## Calculate each row's difference from the group mean
DT[,mpg_diff_from_group := mpg - group_mpg_avg]

print(DT)

#     mpg cyl am gear group_mpg_avg mpg_diff_from_group
# 1: 21.4   6  0    3         19.75                1.65
# 2: 18.1   6  0    3         19.75               -1.65
# 3: 19.2   6  0    4         18.50                0.70
# 4: 17.8   6  0    4         18.50               -0.70
# 5: 21.0   6  1    4         21.00                0.00
# 6: 21.0   6  1    4         21.00                0.00
# 7: 19.7   6  1    5         19.70                0.00
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...