繁体   English   中英

r-如果满足条件,则对某些行重新排序

[英]r - reorder certain rows if condition is met

我有一个数据框,其中某些行需要重新排序。 例如:

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来完成(如果tidyverse则可以使用tidyverse吗?)?

也许那样吗? 但是我并没有理解您对无处可去或不止一个地方的“ 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)

由于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 最后,用ifelse更新排列向量gr并进行排列。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM