От нескольких записей для одного ID к одной в R

топ 100 блогов answer_42 — 19.09.2010 Таймыр называет это "перекрестным запросом", ну пусть будет хоть зеброй, главное чтоб работало. Итак.

Стандартная ситуация - есть записи в таблице, для каждой - ID, но некоторые записи имеют один ID. Например ситуация такая, есть таблица с почвами, некоторые - чистые, а некоторые комплексы, таким образом, каждый уникальный почвенный выдел (определяется по ID) может быть представлен одной или несколькими записями.

Дальше, чтобы работать с такой таблицей при идентификации выдела можно конечно делать один-ко-многим, но хочется другого. Хочется разложить данные так, чтобы запись для одного ID была одна, а доп. данные "встали" в новые колонки.

Пример:
x = data.frame(cbind(c(1,2,2,4),trunc(runif(4,0,10)),trunc(runif(4,0,10))),trunc(runif(4,0,10)))
names(x) = c("ID","A","B","C")
x
   ID A B C
1 1 0 0 4
2 2 5 4 5
3 2 1 4 7
4 4 2 7 6
Итак, у нас 4 записи, но 3 уникальных ID. Один из них, двойка - составной, представлен двумя записями. Решать будем так: 
  1.  Составим список уникальных идентификаторов
  2. Определим максимальное количество записей на один идентификатор - частотной таблицей
  3. По этому числу создадим эквивалентное количество наборов полей, т.е. если были поля A B C и макс=2, то будет A B C A2 B2 C2
  4. Дальше выбираем данные по идентификатору, распластываем, добавляем NA недостающие до макс. числа полей и т.д.
Результат (для примера выше):
   ID A B C A1 B1 C1
1 1 0 0 4 NA NA NA
2 2 5 4 5 1 4 7
3 4 2 7 6 NA NA NA
Полный код под катом
  x = data.frame(cbind(c(1,2,2,4),trunc(runif(4,0,10)),trunc(runif(4,0,10))),trunc(runif(4,0,10)))
names(x) = c("ID","A","B","C")

idfname = "ID"
idfpos = which(names(x) == idfname)

#determine number of unique IDs
ids = unique(x[,idfpos])

#determine maximum number of repeats
maxrepeats = max(as.vector(table(x[,idfpos])))

#add fields
nms = names(x)
nms2 = nms
for (i in 1:(maxrepeats-1)) {
    nms2 = c(nms2,paste(nms,i,sep="")[-1])
}
nms = nms2

res = NULL
for (id in ids) {
    d = subset(x,x$ID == id)
    y = as.numeric(d$ID[1])
    for (i in 1:dim(d)[1]) {
        y = c(y,as.numeric(d[i,2:length(d)]))
    }
    
    if (length(y) != length(nms)) {
        y = c(y,rep(NA,length(nms)-length(y)))
    }
    res = rbind(res,y)
}
res = data.frame(res)
names(res) = nms 

Оставить комментарий

Архив записей в блогах:
Спасибо jananov , сообщила, что сегодня у Инны именины – 2 февраля А я их никогда не запоминаю) Тёзка vera_vs с праздником нас и других Инн. ...
Точечная сварка стала широко использоваться на разных предприятиях, в том числе и в автосервисах. Ведь гораздо проще вмятину вытянуть снаружи, не усложняя весь процесс снятием самой детали и обивки салона. Терминология и особенность Еще не так и давно опытный рихтовщик был драгоцен ...
Всем добрый вечер, пареньки и девчоночки, вопросик разрешите? Вопросик такой (это к москвичам): пущают ли на подземную парковку Ашан-Тройки ебать-высокие цельнометаллические фургоны? Намерен заехать в Леруа Мерлен тамошний, прикупить мешочков ...
Песков назвал голословным заявление CNN о якобы подготовке Россией провокации в Донбассе 14 января 2022, 20:21 Заявление американского телеканала CNN о якобы подготовке российскими спецслужбами провокации в Донбассе является голословным и ничем не подтверждённым. Об этом заявил ...
Самые хитрожопые на свете это не люди, а пауки из семейства Pisauridae. Самец берёт муху, заворачивает её в кокон из паутины, и несёт полюбившейся самке: "Вот, смотри, я тебе мамонта принёс!" Самка сразу млеет от счастья, и пока разворачивает подарок – самец самым наглым образом ею ...