Создайте матрицу из двух столбцов информационного кадра и заполните ее третьим без вложенного цикла for - PullRequest
0 голосов
/ 29 июня 2018

Скажем, у меня есть датафрейм с тремя столбцами

> df
A    B    C
1232    27.3    0.42
1232    27.3    0.36
1232    13.1    0.15
7564    13.1    0.09
7564    13.1    0.63

Требуемый вывод:

        [1232]    [7564]
[13.1]   0.15    0.36
[27.3]   0.39    0

Мне нужно сделать матрицу с уникальными значениями в A и B в качестве моих строк и столбцов. Значение для любой ячейки в матрице должно быть рассчитано путем поднабора исходного кадра данных для конкретного значения A и B и вычисления среднего значения для столбца C.

Мой код:

mat <- matrix(rep(0), length(unique(df$A)), nrow = length(sort(unique(df$B))))
# sort is to avoid NA
colnames(mat) <- unique(df$A)
rownames(mat) <- unique(df$B)

for (row in rownames(mat)) {
    for (col in colnames(mat)) {
        x <- subset(df, A == col & B == row)
        mat[row, col] = mean(df$C)
     }
}

Это очень медленно, учитывая, что мне приходится иметь дело с матрицей, которая имеет тысячи строк и столбцов. Как я могу сделать это быстрее?

Ответы [ 3 ]

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

Вы можете использовать комбинацию aggregate() и xtabs():

df <- read.table(header=TRUE, stringsAsFactors = FALSE, text=
"A    B    C
1232    27.3    0.42
1232    27.3    0.36
1232    13.1    0.15
7564    13.1    0.09
7564    13.1    0.63")
xtabs(C ~ B + A, data=aggregate(C ~ B + A, data=df, FUN=mean))
# > xtabs(C ~ B + A, data=aggregate(C ~ B + A, data=df, FUN=mean))
#       A
# B      1232 7564
#   13.1 0.15 0.36
#   27.3 0.39 0.00

Для других решений читайте: Как преобразовать данные из длинного в широкий формат?

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

Tidyverse решение:

library(tidyverse)

df %>% 
  group_by(A, B) %>%
  summarise(C = mean(C)) %>%
  spread(A, C)
0 голосов
/ 29 июня 2018

Вы, вероятно, хотите что-то вроде этого: (используя data.table)

n <- 1e3
v <- LETTERS[1:5]
set.seed(42)
df <- data.frame(A = sample(v, n, replace = T),
                 B = sample(v, n, replace = T),
                 C = sample.int(1e2, n, replace = T))


require(data.table)
dt <- as.data.table(df)
r <- dt[, .(v = mean(C)), keyby = .(A, B)] # calculate mean for each combination
r <- dcast(r, B ~ A, value.var = 'v') # transform to your structure
rmat <- as.matrix(r[, -1]) # to matrix
rownames(rmat) <- r[[1]] # add row names
rmat[1:5, 1:5]
#          A        B        C        D        E
# A 53.00000 42.71739 53.11538 49.35000 53.14286
# B 50.62745 58.41379 60.43590 48.75000 56.56410
# C 43.75000 42.93548 55.45000 52.63415 44.27907
# D 50.00000 49.84314 57.48276 50.37143 53.16667
# E 43.95122 55.46667 55.38095 43.85366 53.22222

P.S. Ваш опубликованный код был неверным. петли должны быть:

for (row in rownames(mat)) {
  for (col in colnames(mat)) {
    x <- subset(df, A == col & B == row)
    mat[row, col] = mean(x$C)
  }
}

P.S.S. цикл может быть оптимизирован как:

for (row in rownames(mat)) {
  for (col in colnames(mat)) {
    i <- (df$A == col & df$B == row)
    mat[row, col] <- mean(df[i, 'C'])
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...