Р: как применить функцию к некоторым столбцам в группы данных? - PullRequest
0 голосов
/ 07 октября 2018

Я ценю вашу помощь в применении функции для группировки фреймов данных по некоторым столбцам.Я полагаю, мне нужно использовать какую-то функцию dplyr или lapply или do.call, но я не смог этого сделать.

У меня есть следующий фрейм данных:

dfFull <- data.frame(Cen = c("Cen01", "Cen01", "Cen01", "Cen01",
                             "Cen01", "Cen01", "Cen01", "Cen01", 
                             "Cen02", "Cen02", "Cen02", "Cen02", 
                             "Cen02", "Cen02", "Cen02", "Cen02"), 
                     Model = c("Mod01", "Mod01", "Mod01", "Mod01", 
                               "Mod02", "Mod02", "Mod02", "Mod02",
                               "Mod01", "Mod01", "Mod01", "Mod01",
                               "Mod02", "Mod02", "Mod02", "Mod02"), 
                     Indiv = c(1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4), 
                     PF = c(1,1,2,2,1,1,2,2,1,1,2,2,1,1,2,2), 
                     Obj1 = c(0.0,0.02,0.01,0.03,0.01,
                              0.0,0.02,0.0,0.15,0.03, 
                              0.02,0.08,0.1,0.06,0.02,0.09), 
                     Obj2 = c(0.8,0.62,0.85,0.7,0.92,
                              0.26,0.85,0.93,0.03,0.84, 
                              0.94,0.84,0.05,0.63,0.83,0.92))

Мне нужно вызвать функцию (из пакета emoa ):

  • dominated_hypervolume(matrix_points, refp), которая вычисляет hypervolume для matrix_point с использованием предварительно определенного refp.
  • refp - это вектор (RP <- c(1.0,1.0)), используемый для каждого расчета.

Проблема связана с matrix_points:

  • matrix_points - это матрица, которая транспонирована по сравнению с моим фреймом данных.
  • Мне нужно это hypervolume, рассчитанное с использованием Obj1 и Obj2 всех индивидуумов, сгруппированных по Cen , Mod и PF столбцы.

Используя небольшие данные, я знаю, что dominated_hypervolume выполнит эту работу, поскольку я смогу предоставить правильные данные.

Я знаю, что это неправильно, но я пыталсясделать что-то вроде:

dfFull <- dfFull %>%
  group_by(Cen, Model, PF) %>%
  do.call(HV =dominated_hypervolume(data.matrix(t(dfFull[,5:6]), RP)))

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

Cen     Model   PF   Indiv    Obj1   Obj2    HV
Cen01   Mod01    1     1      0.0    0.8     0.77 
Cen01   Mod01    1     2      0.02   0.62    0.77
Cen01   Mod01    2     3      0.01   0.85    0.74
Cen01   Mod01    2     4      0.03   0.70    0.74
Cen01   Mod02    1     1      0.01   0.92    0.81
Cen01   Mod02    1     2      0.0    0.26    0.81
Cen01   Mod02    2     3      0.02   0.85    0.69
Cen01   Mod02    2     4      0.0    0.93    0.69
Cen02   Mod01    1     1      0.15   0.03    0.88 
Cen02   Mod01    1     2      0.03   0.84    0.88
Cen02   Mod01    2     3      0.02   0.94    0.86
Cen02   Mod01    2     4      0.08   0.84    0.86
Cen02   Mod02    1     1      0.1    0.05    0.76 
Cen02   Mod02    1     2      0.06   0.63    0.76
Cen02   Mod02    2     3      0.02   0.83    0.64
Cen02   Mod02    2     4      0.09   0.92    0.64

Спасибо за вашу помощь.

Ответы [ 2 ]

0 голосов
/ 08 октября 2018

Рассмотрим by (объектно-ориентированную оболочку tapply для группировки), чтобы передать сгруппированные подсети для запуска необходимого определенного метода, а затем привести к data.frame():

grpcols <- c("Cen", "Model", "PF")

df_list <- by(dfFull, dfFull[grpcols], function(sub)
  data.frame(Cen = sub$Cen[[1]],
             Model = sub$Model[[1]],
             PF = sub$PF[[1]],
             HV = dominated_hypervolume(t(sub[,5:6]), RP))
  )

И затем обработать списокфреймов данных:

# BASE PROCESSING
final_df <- do.call(rbind, df_list)
final_df <- with(final_df, final_df[order(Cen, Model, PF),])
row.names(final_df) <- NULL

final_df <- merge(dfFull, final_df[c(grpcols, "HV")], by=c("Cen", "Model", "PF"))
final_df
#      Cen Model PF Indiv Obj1 Obj2     HV
# 1  Cen01 Mod01  1     1 0.00 0.80 0.3764
# 2  Cen01 Mod01  1     2 0.02 0.62 0.3764
# 3  Cen01 Mod01  2     3 0.01 0.85 0.2940
# 4  Cen01 Mod01  2     4 0.03 0.70 0.2940
# 5  Cen01 Mod02  1     1 0.01 0.92 0.7400
# 6  Cen01 Mod02  1     2 0.00 0.26 0.7400
# 7  Cen01 Mod02  2     3 0.02 0.85 0.1484
# 8  Cen01 Mod02  2     4 0.00 0.93 0.1484
# 9  Cen02 Mod01  1     1 0.15 0.03 0.8437
# 10 Cen02 Mod01  1     2 0.03 0.84 0.8437
# 11 Cen02 Mod01  2     3 0.02 0.94 0.1508
# 12 Cen02 Mod01  2     4 0.08 0.84 0.1508
# 13 Cen02 Mod02  1     1 0.10 0.05 0.8698
# 14 Cen02 Mod02  1     2 0.06 0.63 0.8698
# 15 Cen02 Mod02  2     3 0.02 0.83 0.1666
# 16 Cen02 Mod02  2     4 0.09 0.92 0.1666

Или с обработкой dplyr, все еще использующей вывод base::by(), где do.call, order, merge становится bind_rows, arrange, inner_join соответственно:

# DPLYR PROCESSING
attributes(df_list) <- NULL

final_df <- bind_rows(df_list) %>%
  arrange(Cen, Model, PF) %>%
  inner_join(dfFull, by=c("Cen", "Model", "PF"))

final_df
#      Cen Model PF     HV Indiv Obj1 Obj2
# 1  Cen01 Mod01  1 0.3764     1 0.00 0.80
# 2  Cen01 Mod01  1 0.3764     2 0.02 0.62
# 3  Cen01 Mod01  2 0.2940     3 0.01 0.85
# 4  Cen01 Mod01  2 0.2940     4 0.03 0.70
# 5  Cen01 Mod02  1 0.7400     1 0.01 0.92
# 6  Cen01 Mod02  1 0.7400     2 0.00 0.26
# 7  Cen01 Mod02  2 0.1484     3 0.02 0.85
# 8  Cen01 Mod02  2 0.1484     4 0.00 0.93
# 9  Cen02 Mod01  1 0.8437     1 0.15 0.03
# 10 Cen02 Mod01  1 0.8437     2 0.03 0.84
# 11 Cen02 Mod01  2 0.1508     3 0.02 0.94
# 12 Cen02 Mod01  2 0.1508     4 0.08 0.84
# 13 Cen02 Mod02  1 0.8698     1 0.10 0.05
# 14 Cen02 Mod02  1 0.8698     2 0.06 0.63
# 15 Cen02 Mod02  2 0.1666     3 0.02 0.83
# 16 Cen02 Mod02  2 0.1666     4 0.09 0.92
0 голосов
/ 08 октября 2018
library(tidyverse)
library(emoa)

RP <- c(1.0,1.0)

dfFull %>%
  nest(-Cen, -Model, -PF) %>%
  mutate(HV = map_dbl(data, ~dominated_hypervolume(t(data.frame(.x$Obj1, .x$Obj2)), RP))) %>%
  unnest()

#      Cen Model PF     HV Indiv Obj1 Obj2
# 1  Cen01 Mod01  1 0.3764     1 0.00 0.80
# 2  Cen01 Mod01  1 0.3764     2 0.02 0.62
# 3  Cen01 Mod01  2 0.2940     3 0.01 0.85
# 4  Cen01 Mod01  2 0.2940     4 0.03 0.70
# 5  Cen01 Mod02  1 0.7400     1 0.01 0.92
# 6  Cen01 Mod02  1 0.7400     2 0.00 0.26
# 7  Cen01 Mod02  2 0.1484     3 0.02 0.85
# 8  Cen01 Mod02  2 0.1484     4 0.00 0.93
# 9  Cen02 Mod01  1 0.8437     1 0.15 0.03
# 10 Cen02 Mod01  1 0.8437     2 0.03 0.84
# 11 Cen02 Mod01  2 0.1508     3 0.02 0.94
# 12 Cen02 Mod01  2 0.1508     4 0.08 0.84
# 13 Cen02 Mod02  1 0.8698     1 0.10 0.05
# 14 Cen02 Mod02  1 0.8698     2 0.06 0.63
# 15 Cen02 Mod02  2 0.1666     3 0.02 0.83
# 16 Cen02 Mod02  2 0.1666     4 0.09 0.92
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...