r - переупорядочить определенные строки, если условие выполнено - PullRequest
0 голосов
/ 17 мая 2018

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

df <- data.frame(name = c(1,1,1,1,1,2,2,2,2,2),
                 id = c("s","s","s","i","s","s","i","s","s","s"),
                 var1 = c(3,5,6,4,-7,2,1,-1,3,-6),
                 var2 = c(2,6,-7,5,-9,7,3,2,4,-9))

В этом кадре данных строки, в которых id == "i" должны быть переупорядочены. Изменение порядка должно выполняться путем сравнения значений в других строках группы (в этом случае столбец name можно использовать для group_by). Условием для переупорядочения является, например, следующее. если текущая строка для проверки является строкой, в которой id == "i", тогда проверьте:

var1 < lead(var1) & var1 > lag(var1) & var2 < lead(var2) & var2 > lag(var2)

Если FALSE, то это означает, что этот ряд следует перемещать до тех пор, пока это условие не станет TRUE.

После переупорядочения конечный продукт должен быть:

df_output <- data.frame(name = c(1,1,1,1,1,2,2,2,2,2),
                        id = c("s","i","s","s","s","s","s","i","s","s"),
                        var1 = c(3,4,5,6,-7,2,-1,1,3,-6),
                        var2 = c(2,5,6,-7,-9,7,2,3,4,-9)) 

Обратите внимание, что в первой группе строка, в которой id == "i" переместилась с 4-й позиции на 2-ю позицию, а во второй группе - с 2-й на 3-ю позицию.

Можно ли это сделать с помощью tidyverse, если это возможно (если не с любым, который работает)?

Ответы [ 2 ]

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

В качестве IMO невозможно / необходимо проверить две переменные для позиции, которую я буду использовать onyl var1.

library(tidyverse)
df %>% 
  group_by(name) %>% 
  mutate(gr1=1:n()) %>% 
  mutate(gr2=first(which(var1 < var1[id =="i"]))) %>% 
  mutate(gr3= ifelse(id=="i", gr2+0.1, gr1)) %>% 
  ungroup() %>% 
  arrange(name, gr3) %>% 
  select(-starts_with("gr"))
# A tibble: 10 x 4
    name id     var1  var2
   <dbl> <fct> <dbl> <dbl>
 1     1 s         3     2
 2     1 i         4     5
 3     1 s         5     6
 4     1 s         6    -7
 5     1 s        -7    -9
 6     2 s         2     7
 7     2 s        -1     2
 8     2 i         1     3
 9     2 s         3     4
10     2 s        -6    -9

Идея состоит в том, чтобы найти для каждой группы name первое var1 значение, меньшее, чем значение * i, используя first.Наконец, обновляя аранжировочный вектор gr на ifelse и аранжируя.

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

Может быть, так? Но я не понял, что вы делали со строками «i», в которых нет места или более одного места. Все было бы намного проще, если бы 's' строки были упорядочены.

dfs <- filter(df, id=="s")
dfi <- filter(df, id=="i")

dfs$x <- (!is.na(lead(dfs$name)) & dfs$name==lead(dfs$name) & dfs$var1<lead(dfs$var1) & dfs$var2<lead(dfs$var2)) |
         (!is.na(lag(dfs$name))  & dfs$name==lag(dfs$name)  & dfs$var1>lag(dfs$var1)  & dfs$var2>lag(dfs$var2) )
dfs$y <- row.names(dfs)
dfs1 <- filter(dfs,x) %>% select(-x)
dfs0 <- filter(dfs,!x) %>% select(-x)
dfi$y <- ""
df2 <- arrange(rbind(dfs1,dfi),name,var1,var2)
df2$y <- ifelse(df2$y=="",paste0(lag(df2$y),",",row.names(df2)),df2$y)
df_output <- arrange(rbind(df2,dfs0),y) %>% select(-y)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...