От нескольких записей для одного 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 

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

Архив записей в блогах:
Намедни жыдобендеровское толковище (известное под кодовым наименованием Верховная Рада Украины) приняла наконец пакет законов, заставивший уже было гаснущие ватные пуканы возгореться с новой силой. В преддверии дня Великой Скойбеды укрофашисты порешили: 1) переименовать Великую Отечественн ...
А вот теперь доказывай всем, что ты имел в виду, а вот теперь попробуй уснуть, как ты хотел, в одиннадцать. И тот, кто в спину тебе кричал, что ты будешь гореть в аду, закрылся в доме на два ключа, чтобы тебе присниться. А вот теперь не гляди на мир рассеянно, как в бреду, поди-ка верни ...
Начнём, пожалуй, с зерна. Его сбор в России в чистом весе в 2021 году составил 120,7 млн тонн, в том числе 75,9 млн тонн пшеницы. Да, здесь мы сделали шаг назад. Ведь по итогам прошлого года урожай зерна составил 133,5 млн тонн, в том числе пшеницы - 85,9 млн тонн. Сбор ржи в 2021 году ...
#ДЕКАБРЬ2010УФА   Первые дни декабря в моем ЖЖ пишет Маша, потому что меня срочно увезли удалять тромб.  На мое нельзя ли отложить до понедельника  хирург сказал: или кладбище,  или в больницу немедленно, выбирайте. И Митя меня мигом отвез не растрёс. В больницу, ...
Подошел к концу третий болотный год. Самое время подвести итоги и понять насколько быстро Hunt сдает своих хардкорные позиции, становясь все более и более казуальной игрой. В прошлой статье я уже упоминал о том, что игра переориентировалась на массового игрока, сделав ставку на ...