Создание групп на основе комбинации столбцов, не заполненных нулями - PullRequest
0 голосов
/ 05 октября 2018

мне трудно решить эту проблему.Я собираюсь объяснить это лучше всего на основе примера, давайте посмотрим на данные ниже:

    order type_a type_b type_c type_d
1     1      0     50     10      0
2     2     10      0      0     80
3     3     15      0      0     35
4     4      0      0     30      0
5     5      0     20     40      0

и dput:

data <- structure(list(order = c(1, 2, 3, 4, 5), type_a = c(0, 10, 15, 
0, 0), type_b = c(50, 0, 0, 0, 20), type_c = c(10, 0, 0, 30, 
40), type_d = c(0, 80, 35, 0, 0)), .Names = c("order", "type_a", 
"type_b", "type_c", "type_d"), row.names = c(NA, -5L), class = "data.frame")

Мы можем видеть, чтоВ первом столбце указан номер заказа, в остальных столбцах указано, что принадлежит к этому заказу.Кроме того, если столбец type_ * заполнен 0, то он не имеет значения.

Я хотел бы создать новый столбец, который определяет группы на основе столбцов «описание заказа» -> type_ *.Например, для порядка 1 и порядка 5 у нас есть одинаковые столбцы type_ *, заполненные без значений 0, поэтому они принадлежат одной и той же группе, то же самое относится к порядку 2 и 3 и т. Д.

Мой окончательный результат должен выглядетьвот так:

   order type_a type_b type_c type_d   group
1     1      0     50     10      0 group_1
2     2     10      0      0     80 group_2
3     3     15     10      0     35 group_2
4     4      0      0     30      0 group_3
5     5      0     20     40      0 group_1

Только для вашей информации, в моих реальных данных у меня больше 4 столбцов type_ * -> их около 10-15!

Спасибо запомощь!

Ответы [ 3 ]

0 голосов
/ 05 октября 2018

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

set.seed(42)
cols <- grep("type_", names(d))
d$group <- kmeans(d[cols], 4)$cluster
# d$group <- paste0("group_", d$group)

Природа кластеризации k-средних такова, что столбцы «всегда» 0 имеют тенденцию оказывать сильное категоризирующее влияние на результаты.

Примечания:

1) Мы используем grep для идентификации столбцов, потому что использование числовых ссылок на имена столбцов в будущем может привести к проблемам, если ваши данные не в той же форме, или изменятсяпозиции.Это также более читабельно для тех, кто просматривает ваш код.

2) Мы должны избегать использования имени переменной data, потому что это функция в базе R.

0 голосов
/ 05 октября 2018

data.table решение

library(data.table)

setDT(data)[, id := .GRP, by = list( do.call(paste0, c( data.frame( data[,2:5] != 0 ) ) ) ) ][, id := paste0( "Group_", id)][]

#    order type_a type_b type_c type_d      id
# 1:     1      0     50     10      0 Group_1
# 2:     2     10      0      0     80 Group_2
# 3:     3     15      0      0     35 Group_2
# 4:     4      0      0     30      0 Group_3
# 5:     5      0     20     40      0 Group_1
0 голосов
/ 05 октября 2018

Ваши группы определяются наличием или отсутствием 0 в столбцах со 2 по 5. Проверьте 0, сверните значения TRUE / FALSE в виде строки и вы получите уникальную строку для каждой группы.Пересчитайте в множитель:

> data$group = factor(apply(data[,2:5] ==0,1,paste,collapse=""))
> data
  order type_a type_b type_c type_d              group
1     1      0     50     10      0 TRUEFALSEFALSETRUE
2     2     10      0      0     80 FALSETRUETRUEFALSE
3     3     15      0      0     35 FALSETRUETRUEFALSE
4     4      0      0     30      0  TRUETRUEFALSETRUE
5     5      0     20     40      0 TRUEFALSEFALSETRUE

Теперь имена безобразны, поэтому измените уровни:

> class(data$group)
[1] "factor"
> levels(data$group)=paste("group_",1:length(levels(data$group)))
> data
  order type_a type_b type_c type_d    group
1     1      0     50     10      0 group_ 2
2     2     10      0      0     80 group_ 1
3     3     15      0      0     35 group_ 1
4     4      0      0     30      0 group_ 3
5     5      0     20     40      0 group_ 2

Если весь этот капитал TRUEFALSE причиняет вам боль, простое исправление сделает аккуратнымдвоичное число:

> data$group = factor(apply(0+(data[,2:5] ==0),1,paste,collapse=""))
> data
  order type_a type_b type_c type_d group
1     1      0     50     10      0  1001
2     2     10      0      0     80  0110
3     3     15      0      0     35  0110
4     4      0      0     30      0  1101
5     5      0     20     40      0  1001
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...