[英]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.