Переставить фрейм данных в соответствии с индексным столбцом - PullRequest
0 голосов
/ 13 апреля 2019

У меня есть фрейм данных, как показано ниже.Я хочу перестроить фрейм данных на основе столбца «Точка останова».

enter image description here

Ожидаемый результат должен быть следующим:

enter image description here

Ответы [ 2 ]

2 голосов
/ 13 апреля 2019

С этими примерами данных:

df <- data.frame(
    Range1 = c(1, 2, 3, 5, 10, 12, 16, 20, 21, 28, 33),
    Range2 = c(2, 3, 5, 10, 12, 16, 20, 21, 28, 33, 40),
    Breakpoint = c("", "", "", "Y", "", "Y", "", "", "Y", "", ""))

Решение с вырезанными концевыми битами:

Сначала обрежьте свисающие биты:

 df2 = df[1:max(which(df$Breakpoint=="Y")),]

Затемопределить длину каждой группы:

> rgroup=rle(rev(cumsum(rev(df2$Break=="Y"))))$lengths

Получить, где Y:

> Ypos = which(df2$Breakpoint=="Y")

Построить индексный вектор, который представляет собой позиции Y минус обратная последовательность от 1 до длиныкусокПодмножество:

> df2[rep(Ypos, rgroup) - unlist(lapply(rgroup,function(x){1:x})) +1,]
  Range1 Range2 Breakpoint
4      5     10          Y
3      3      5           
2      2      3           
1      1      2           
6     12     16          Y
5     10     12           
9     21     28          Y
8     20     21           
7     16     20       

При необходимости снова включить висячие биты.

[править - добавлена ​​новая версия выше.Приведенный ниже код для исторических целей]

Моя старая версия была такой и имела дело с висячими битами:

> group=rev(cumsum(rev(df$Break=="Y")))
> rbind(do.call(rbind,lapply(split(df[group>0,],-group[group>0]),function(x){x[nrow(x):1,,drop=FALSE]}))[,c("Range1","Range2")],df[max(which(df$Break=="Y")),1:2,drop=FALSE],df[group==0,1:2])

и получаю:

     Range1 Range2
-3.4      5     10
-3.3      3      5
-3.2      2      3
-3.1      1      2
-2.6     12     16
-2.5     10     12
-1.9     21     28
-1.8     20     21
-1.7     16     20
9        21     28
10       28     33
11       33     40

Если вы неt, как имена строк, затем отбросьте их.Используются только базовые функции R.

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

БонусАннотированная версия:

> group=rev(cumsum(rev(df$Break=="Y")))

Это создает вектор, который начинается с 0 для последней строки и увеличивается каждый раз, когда он находит Y. Обратный, чтобы получить переменную группировки для кусков вплоть до каждого Y.

Этот бит не сработает, если использовать режущую пасту из-за комментариев, которые я собираюсь сделать:

> rbind(

# we need to bind three things. The reversed chunks, the last break point and   
# the trailing stuff:

      do.call(

# the trailing stuff is the rbind of the reversed chunks:

          rbind,

#           split the data into a list of chunks 

             lapply(
               split(df[group>0,],-group[group>0]),

     # reverse them

                  function(x){x[nrow(x):1,,drop=FALSE]}
     # and only take the columns we need:
        ))[,c("Range1","Range2")],
  # this is the last Y
      df[max(which(df$Break=="Y")),1:2,drop=FALSE],

  # this is the trailing rows, get them in order they appear:

      df[group==0,1:2])

Такое аннотирование позволило мне увидеть некоторые оптимизации, которые можно было бы сделать, но на этом пока все.

0 голосов
/ 13 апреля 2019

В зависимости от размера вашего data.frame это может быть сделано вручную с помощью цикла for.

BreakPoints <- which(!is.na(DF$`break point`))
if(length(breakPoints) > 0){
    startIndex <- 1 #Startindex tells me where i should point the breakPoint
    for(i in breakPoints){ #Iterate over breakpoints
        #Put the break point at the startIndex row 
        DF[startIndex:i,] <- DF[c(i, startIndex:(i-1), ] 
        #Update the placement as the next block 
        startIndex <- i + 1
    }
}

если ваши данные большие, вероятно, существует более эффективный метод.В общем случае подмножество через [<-.dataframe является медленным по сравнению с другими методами.Первоначальный оптимизатор мог бы просто преобразовывать приведенный выше код в формат data.table, где поднаборы выполняются намного быстрее.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...