объединить df из списка и усреднить только по конкретным значениям - PullRequest
2 голосов
/ 14 апреля 2019

У меня есть список DF в R, скажем,

list.data<-list(df1=df1,df2=df2)

все df с одинаковым количеством строк и одинаковым количеством столбцов У меня есть матрица m, созданная значениями ИСТИНА / ЛОЖЬ. Предположим, что df

         [,1]       [,2]
[1,] -1.8526984 -1.3359316
[2,] -0.9391172 -1.4453051
[3,]  0.2793443 -1.0223621
[4,]  2.0174213 -1.1734235
[5,]  0.2100461 -0.1261543

и df2 равно

           [,1]       [,2]
[1,]  -1.8526984  0.1956987
[2,]  0.1737456 -1.4453051
[3,]  1.7133539  0.4562011
[4,] -0.6132369 -0.3532976
[5,] -0.5008479  1.5729352

и моя матрица m равна

      [,1]  [,2]
[1,] FALSE  TRUE
[2,]  TRUE FALSE
[3,] TRUE TRUE
[4,] TRUE TRUE
[5,] TRUE  TRUE

Я хочу объединить df, содержащийся в моем list.data объекте, в один фрейм данных, получая среднее значение только по элементам i-й строки и j-го столбца, помеченным как TRUE матрицей m, в то время как другие элементы кадры данных нетронуты.

Пример: Конечный кадр данных должен представлять собой матрицу 5 x 2, и, например, элемент (2,1) должен быть средним между df2_ (2,1) и df1_ (2,1), поскольку m_ (2,1) правда. Элемент 1,1 должен быть df1_ (1,1) или df_2 (1,1), поскольку m (1,1) равно FALSE

Спасибо

Ответы [ 2 ]

3 голосов
/ 14 апреля 2019

Похоже, у вас есть список матриц. Мы можем сделать

#Create a matrix to hold the result
result <- matrix(0, ncol = ncol(m), nrow = nrow(m))

#Find indices to calculate mean
inds <- which(m)

#Indices for which the values is to be taken as it is
non_inds <- which(!m)

#Subset the indices from list of matrices and take their mean
result[inds] <- rowMeans(sapply(list.data, `[`, inds))

#Subset the indices from first list as it is
result[non_inds] <- list.data[[1]][non_inds]


result
#           [,1]       [,2]
#[1,] -1.8526984 -0.5701164
#[2,] -0.3826858 -1.4453051
#[3,]  0.9963491 -0.2830805
#[4,]  0.7020922 -0.7633606
#[5,] -0.1454009  0.7233905

Данные

list.data <- list(df1 = structure(c(-1.8526984, -0.9391172, 0.2793443, 
2.0174213, 
0.2100461, -1.3359316, -1.4453051, -1.0223621, -1.1734235, -0.1261543
), .Dim = c(5L, 2L), .Dimnames = list(NULL, c("V1", "V2"))), 
df2 = structure(c(-1.8526984, 0.1737456, 1.7133539, -0.6132369, 
-0.5008479, 0.1956987, -1.4453051, 0.4562011, -0.3532976, 
1.5729352), .Dim = c(5L, 2L), .Dimnames = list(NULL, c("V1", 
"V2"))))
2 голосов
/ 14 апреля 2019

Вот один вариант без инициализации матрицы

out <- Reduce(`+`, lapply(list.data, function(x) x * NA^!m ))/2
replace(out, is.na(out), list.data[[1]][is.na(out)])
#            V1         V2
#[1,] -1.8526984 -0.5701164
#[2,] -0.3826858 -1.4453051
#[3,]  0.9963491 -0.2830805
#[4,]  0.7020922 -0.7633606
#[5,] -0.1454009  0.7233905

или в одну строку с coalesce

library(dplyr)
coalesce(Reduce(`+`, lapply(list.data, function(x) x * NA^!m ))/2, list.data[[1]])

или то же самое в трубе

library(tidyverse)
library(magrittr)
map(list.data, ~ .x * NA^ !m ) %>%
           reduce(`+`) %>%
           divide_by(2) %>%
           coalesce(list.data[[1]])

данные

list.data <- list(df1 = structure(c(-1.8526984, -0.9391172, 0.2793443, 
2.0174213, 
0.2100461, -1.3359316, -1.4453051, -1.0223621, -1.1734235, -0.1261543
), .Dim = c(5L, 2L), .Dimnames = list(NULL, c("V1", "V2"))), 
df2 = structure(c(-1.8526984, 0.1737456, 1.7133539, -0.6132369, 
-0.5008479, 0.1956987, -1.4453051, 0.4562011, -0.3532976, 
1.5729352), .Dim = c(5L, 2L), .Dimnames = list(NULL, c("V1", 
"V2"))))

m <- structure(c(FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, 
TRUE, TRUE), .Dim = c(5L, 2L))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...