Я бы сделал это, используя пакет reshape2
. Я создал минимальный набор данных, чтобы проиллюстрировать это:
set.seed(42)
dataset <- expand.grid(letters[1:4], LETTERS[1:4])
dataset$total <- rpois(16, 1)
names(dataset) <- c("source.category", "target.category", "total")
# set the last row to the first row to illustrate fill and aggregate
dataset[16, ] <- dataset[1, ]
Затем просто используйте функцию acast
, чтобы создать матрицу, и, наконец, нормализуйте суммы строк до 1.
require(reshape2)
# reshape to wide format
res <- acast(
dataset, # the dataset
source.category ~ target.category, # the margins of the result
value.var = "total", # which variable should be in the cells
fill=0L, # fill empty cells with this value
fun.aggregate = sum # aggregate double cells with this function
)
# normalize rowSums to 1
res <- res / rowSums(res)
# this is your result
res
Редактировать: на больших наборах данных это будет длиться вечно или даже потерпеть неудачу. Для больших наборов данных используйте разреженные матрицы из пакета Matrix
, это намного быстрее и дает результат, который намного меньше в хранилище.
require(Matrix)
dataset$target.category <- factor(dataset$target.category)
dataset$source.category <- factor(dataset$source.category)
res <- sparseMatrix(
as.integer(dataset$target.category),
as.integer(dataset$source.category),
x = dataset$total
)
res <- res/rowSums(res)
Это достаточно быстро для всего набора данных, чтобы работать в интерактивном режиме.