#r #dplyr #tidyverse
#r #dplyr #tidyverse
Вопрос:
У меня есть фрейм данных со значениями для 50 идентификаторов, повторяющихся в течение 10 итераций. Я хотел бы подмножество по идентификатору, а затем выполнить вычисления и повторить это для каждого столбца от x1
до x5
. Я использовал цикл for, но он очень неэффективен (мой фактический набор данных имеет намного больше идентификаторов).
Вот вычисления, которые я хотел бы выполнить. У меня был переменный успех с преобразованием в dplyr:
- Первое вычисление дает мне правильное значение для
x1
, но необходимо повторить для каждого столбца отx1
доx5
.
V1.x1 <- preds.df %>%
split(.$ID) %>%
sapply(function(ID) {
(ID$x1 - mean(ID$x1))^2 # for X1 only
}) %>%
mean()
- Другое вычисление, которое включает вычитание из соответствующего значения в другом df
data.pop
. Моя попытка dplyr неверна даже для всегоx1
:
## This is what I want to achieve, which I implemented using for-loop:
# df for for-loop
Bsq.perID <- data.frame(matrix(NA,
nrow = nrow(data.pop), # 50 observations
ncol = 5) # 5 models
# For-loop:
for (ids in 1:nrow(data.pop)){
current.ID <- preds.df[preds.df$ID == ids, ] # get current ID over all 10 iterations
for (i in 1:5){
Bsq.perID[ids, i] <- (mean(current.ID[, i]) - data.pop[ids, "real.val"])^2
}
}
Bsq.values <- colMeans(Bsq.perID)
## My wrong dplyr attempt of the above:
B1.x1 <- preds.df %>%
split(.$ID) %>%
sapply(function(ID) {
(mean(ID$x1) - data.pop$real.val)^2
}) %>%
mean()
Структура preds.df
выглядит следующим образом:
head(preds.df)
x1 x2 x3 x4 x5 iteration ID
1 20.005984 6.78242996 3.526411 21.463892 8.792720 1 1
2 2.890490 7.28232755 18.670470 6.717213 19.830930 1 2
3 4.868658 24.88117301 1.883913 3.897779 14.371414 1 3
4 6.495532 5.79591685 7.745554 20.153269 7.935672 1 4
5 19.297779 0.05068784 21.744816 14.957751 14.232126 1 5
6 7.090456 22.06322779 8.388263 10.672151 9.921884 1 6
tail(preds.df)
x1 x2 x3 x4 x5 iteration ID
495 16.306927 2.8873609 9.7764755 23.798867 10.246443 10 45
496 4.767296 23.2086303 8.8394391 7.806442 24.898483 10 46
497 19.966301 13.7151699 10.2483011 15.199162 9.658736 10 47
498 18.134534 22.1658901 5.6481757 18.501411 23.787457 10 48
499 7.877636 7.2356274 8.2862336 3.790823 11.610848 10 49
500 8.554774 0.9199501 0.9650191 17.155611 1.158619 10 50
Комментарии:
1. Можете ли вы опубликовать данные, которые вы используете?
2. Да, пожалуйста, найдите его здесь drive.google.com/drive/folders /…
Ответ №1:
Я бы подошел к этому так:
library(dplyr)
library(rio)
preds.df <- import("~/Downloads/preds.df.csv")
data.pop <- import("~/Downloads/data.pop.csv")
## added a row because data.pop is only 49 rows in the data you sent
data.pop <- bind_rows(data.pop, data.pop[1,])
Для этого можно использовать dplyr
with mutate()
:
dat1 <- preds.df %>%
group_by(ID) %>%
mutate(across(x1:x5, function(x)(x-mean(x))^2))
Затем для второй части вы можете объединить данные
data.pop <- data.pop %>%
mutate(ID = 1:n())
dat2 <- dat1 %>% left_join(data.pop)
Затем суммируйте по идентификатору, чтобы вычислить среднее значение x1
с x5
точностью ID
до, затем из каждого вы можете вычесть real.val
и возвести в квадрат.
dat2 <- dat2 %>%
select(c(ID, x1:x5, real.val)) %>%
group_by(ID) %>%
mutate(across(x1:x5, function(x)(x-real.val)^2)) %>%
summarise_all(mean) %>%
select(-real.val)
Комментарии:
1. Часть 1 сработала. Спасибо! Что касается второго, то при удалении
summarise_all(mean)
я получаю ответы, которые близки, но все еще не верны. Моя цель состоит в том, чтобы для каждого столбца взять среднее значение x для каждого идентификатора по итерациям, затем вычесть это среднее значение из real.val этого идентификатора и возвести его в квадрат. Повторите для всех идентификаторов, всех 5 столбцов. Затем используйтеcolMeans()
для возврата 5 значений в конце. В основном я вычисляю смещение ^ 2 для каждой модели здесь.2. После дальнейшей проверки я понял, что все работает правильно до тех пор, пока
summarise_all(mean)
ошибка не заключается в вычитании соответствующих идентификаторовreal.val
из каждого значения.3. @fluent, если вы поменяете местами инструкции summarise_all и mutate, которые должны это сделать. То, что происходило выше, заключалось в том, что он получал среднее значение, а затем вычитал
real.val
из среднего и возводил в квадрат, а не наоборот.