Заменить наборы строк в таблице данных одной строкой - PullRequest
0 голосов
/ 12 мая 2018

У меня есть следующий data.table

 DT<- data.table(id=c(1,1,1,1,2,2,2,2),
            place = c("a","b","c","d","a","b","d","e"),
            seq = c(1,2,3,4,1,2,3,4))
 setkey(DT,id)   

data.table упорядочен по id и seq:

setorder(DT,id,seq)

Для каждого идентификатора я хочу найти последовательностьb, c, d и, если есть такая вещь, я хочу заменить строки с b и c одной строкой, скажем, z (сохраняя данные других столбцов, как в строке с a).

Так что в этом случае новый data.table должен быть

DT.tobe<- data.table(id=c(1,1,1,2,2,2,2),
                     place = c("a","z","d","a","b","d","e"),
                     seq = c(1,2,4,1,2,3,4))
> DT.tobe
   id place seq
1:  1     a   1
2:  1     z   2
3:  1     d   4
4:  2     a   1
5:  2     b   2
6:  2     d   3
7:  2     e   4

Я должен сказать, что понятия не имею, что попробовать ... Я мог бы принять ответы и с решениями data.frame!

Ответы [ 2 ]

0 голосов
/ 14 мая 2018
res = setkey(DT[, {
  w = setDT(shift(place, 0:2, type="lead"))[.("b","c","d"), on=.(V1,V2,V3), which=TRUE, nomatch=0]
  if (length(w)){
    w2 = c(w, w + 1L)
    rbind(
      .SD[-w2],
      copy(.SD[w])[, place := "z"]  
    )
  } else .SD
}, by=id], id, seq)

, что дает

   id place seq
1:  1     a   1
2:  1     z   2
3:  1     d   4
4:  2     a   1
5:  2     b   2
6:  2     d   3
7:  2     e   4

Позиции w находятся с помощью объединения против последовательности b, c, d. Оттуда мы определяем, какие строки отбрасывать (w плюс одна после нее); какие строки сохранить (w); и что в них изменить (place: = "z").

Существует слишком много разных направлений, в которых это можно обобщить, поэтому, возможно, лучше просто опубликовать новый вопрос, если возникнет более сложный случай.

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

Подход должен заключаться в группировании по id и оценке условия / флага, где place == "b" и place == "c" больше 0 (то есть оба b & c доступны для id).Этот флаг (скажем, ReplB решает, будет ли b заменен на z для этого id. Кроме того, тот же флаг (ReplB) используется для фильтрации строк с place == "c" для id.

library(data.table)

DT<- data.table(id=c(1,1,1,1,2,2,2,2),
                place = c("a","b","c","d","a","b","d","e"),
                seq = c(1,2,3,4,1,2,3,4))
setkey(DT,id) 

setorder(DT,id,seq)

DT[,ReplB := sum(place == "b") > 0 & sum(place == "c") >0 ,by=id][
  !(ReplB & place == "c"),.(id, place = ifelse(place=="b" & ReplB,"z",place),seq)]

Обновлено: Для проверки состояния place (то есть a-b-c-d-e) в последовательности.

Подход: => Получить позицию каждогоместо от letters и разность позиций должна быть 1, чтобы обеспечить последовательность мест.

DT[,ReplB := all(diff(mapply(function(x)which(letters==x),place)) == 1),by=id][
  !(ReplB & place == "c"),.(id, place = ifelse(place=="b" & ReplB,"z",place),seq)]
#    id place seq
# 1:  1     a   1
# 2:  1     z   2
# 3:  1     d   4
# 4:  2     a   1
# 5:  2     b   2
# 6:  2     d   3
# 7:  2     e   4
...