Подсчет вхождений переменной, имеющей два заданных значения, соответствующих одному значению другой переменной - PullRequest
0 голосов
/ 23 мая 2018

Как видно на рисунке, у меня есть столбец с номерами заказов и столбец с номерами материалов.

Я хочу выяснить, как часто пара материалов встречается в одном и том же порядке.

Проблема в том, что у меня 30000 строк номеров заказов и 700 уникальных номеров материалов.Возможно ли это вообще?

Я думал, было бы проще создать матрицу с 700 номерами материалов как в строках и столбцах, так и в числе чисел.

PICTURE

РЕДАКТИРОВАТЬ: первое изображение не было хорошим примером.Я загрузил эту вторую картинку со случайными номерами материалов.Поэтому я хочу, чтобы он подсчитал для каждой пары (например, 10-11, как я выделил), сколько раз они появляются в том же порядке.Как видно, 10 и 11 появляются в 3 разных порядках.

PICTURE2

Ответы [ 2 ]

0 голосов
/ 23 мая 2018

Вот решение data.table

library(data.table)    
combis <- data.table(do.call(rbind, 
    DT[, if (.N > 1) list(combn(Materials, 2, simplify=FALSE)), by=Order.number]$V1
))
ans <- combis[, .N, by=.(V1, V2)]

#check results
setorder(ans, V1, V2)
ans

И метод base:

allComb <- by(DT, DT$Order.number, function(x) {
    if (nrow(x) > 1) {
        return(combn(x$Materials, 2, simplify=FALSE)))
    }
    NULL
}
materialsPairs <- as.data.frame(do.call(rbind, unlist(allComb, recursive=FALSE)))

#https://stackoverflow.com/a/18201245/1989480
res <- aggregate(cnt ~ ., data=transform(materialsPairs, cnt=1), length)

#check results
head(res[order(res$V1, res$V2),])

данные:

library(data.table)
set.seed(0L)
M <- 30e3
nOrd <- 3000
DT <- data.table(Order.number=sample(nOrd, M, replace=TRUE), 
    Materials=sample(700, M, replace=TRUE))
setorder(DT, Order.number, Materials)
0 голосов
/ 23 мая 2018

Оптимальным решением с точки зрения пространства памяти будет одна строка для каждой пары, которая будет 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 должна содержать все, что вам нужно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...