Возможно ли такое изменение данных?
Вопрос
У меня есть структура данных, которая выглядит следующим образом:
groupA1 groupA2 groupB1 groupB2 date text
0 1 1 1 2013-01-01 the dog
Для каждого groupB
переменной, я хочу перечислить одну строку для каждого столбца со значением 1.Мне нужно перечислить все комбинации groupA
и groupB
где единицы присутствуют в одной строке, но затем также добавьте дату и текст к каждой из этих комбинаций в виде столбцов в этой строке.
Преобразованные данные будут выглядеть так:
var_groupB var_groupA date text
groupB1 groupA2 2013-01-01 the dog
groupB2 groupA2 2013-01-01 the dog
Я пробовал комбинации melt
и ddply
но я всегда остаюсь без одной из нужных мне переменных.
Одна вещь, которую я попробовал, была melt(x, id.vars=c("text", "date"))
но тогда я теряю всю информацию об отношениях между groupA
и groupB
.
Я мог бы сделать это, используя беспорядочный цикл, но не был уверен, что reshape
существует утилита, о которой я не знаю, и которая могла бы выполнить эту работу.
Решение
Вы могли бы melt
дважды, по одному для каждой группы:
y <- melt(x, measure.vars=c("groupA1", "groupA2"),
variable.name="var_groupA", value.name="val_groupA")
y <- melt(y, measure.vars=c("groupB1", "groupB2"),
variable.name="var_groupB", value.name="val_groupB")
Это даст вам одну строку для каждой комбинации A и B:
date text var_groupA val_groupA var_groupB val_groupB
1 2013-01-01 the dog groupA1 0 groupB1 1
2 2013-01-01 the dog groupA2 1 groupB1 1
3 2013-01-01 the dog groupA1 0 groupB2 1
4 2013-01-01 the dog groupA2 1 groupB2 1
Затем вы можете подмножество этого и удалить столбцы значений:
y <- y[y$val_groupA == 1 & y$val_groupB==1, ]
y <- y[, c("var_groupA", "var_groupB", "date", "text")]
Что дает вам то, что вы хотите:
var_groupA var_groupB date text
2 groupA2 groupB1 2013-01-01 the dog
4 groupA2 groupB2 2013-01-01 the dog
Конечно, если ваш набор данных более сложен, чем в вашем примере, вы можете сделать это решение более элегантным, выполнив объединение и подмножество более автоматизированным способом - например, обнаружив групповые столбцы и заполнив их. measure.vars
, variable.name
, и value.name
автоматически, возможно, для любого количества групп.
Другие советы
Первые два оператора заменяют каждый 0 в первых 4 столбцах на "" и каждую 1 на имя столбца, дающее dd2
.Следующие два утверждения генерируют все комбинации groupA
и groupB
для каждой строки, используя expand.grid
с результатом dd3
.Окончательно subset
что для тех строк, где нет ""
записи:
newvals <- function(nm) ifelse(dd[[nm]] == 0, "", nm)
dd2 <- replace(dd, 1:4, lapply(names(dd)[1:4], newvals))
combo <- function(x) data.frame(expand.grid(groupA=c(x[1:2]), groupB=c(x[3:4])),
x$date, x$text)
dd3 <- do.call("rbind", by(dd2, 1:nrow(dd2), combo))
subset(dd3, groupA != "" & groupB != "")
Это дает:
groupA groupB x.date x.text
1.2 groupA2 groupB1 2013-01-01 the dog
1.4 groupA2 groupB2 2013-01-01 the dog