Оптимальным решением с точки зрения пространства памяти будет одна строка для каждой пары, которая будет 700 * 699/2. Эта проблема все еще относительно мала, и простота манипулирования матрицей 700 * 700, вероятно, более ценна, чем 700* 701/2 ячейки, которые вы сохраняете, что позволило бы получить до 240 КБ с одним байтом на ячейку.Это может быть даже меньше, если матрица разрежена (т.е. большинство пар материалов никогда не упорядочиваются вместе), и вы используете соответствующую структуру данных.
Вот как будет выглядеть код:
Сначаламы хотим создать фрейм данных с таким количеством строк и столбцов, сколько имеется материалов.Матрицы проще создавать, поэтому мы создаем матрицу, которую потом конвертируем в фрейм данных.
all_materials = levels(as.factor(X$Materials))
number_materials = length(all_materials)
Pairs <- as.data.frame(matrix(data = 0, nrow = number_materials, ncol = number_materials))
(Здесь X - ваш набор данных)
Затем мы устанавливаем имена строк и имена столбцов, чтобы иметь возможность прямого доступа к строкам и столбцам с идентификаторами материалов, которые являютсяочевидно, не обязательно нумеруются от 1 до 700.
colnames(Pairs) <- all_materials
rownames(Pairs) <- all_materials
Затем мы перебираем набор данных
for(order in levels(as.factor(X$Order.number))){
# getting the materials in each order
materials_for_order = X[X$Order.number==order, "Materials"]
if (length(materials_for_order)>1) {
# finding each possible pair from the materials list
all_pairs_in_order = combn(x=materials_for_order, m=2)
# incrementing the cell at the line and column corresponding to each pair
for(i in 1:ncol(all_pairs_in_order)){
Pairs[all_pairs_in_order[1, i], all_pairs_in_order[2, i]] = Pairs[all_pairs_in_order[1, i], all_pairs_in_order[2, i]] + 1
}
}
}
В конце цикла таблица Pairs
должна содержать все, что вам нужно.