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

时间:2018-05-17 10:58:17

标签: r dataframe tidyverse

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

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完成此操作(如果没有,那么可以使用JSON.stringify(jdata);)吗?

2 个答案:

答案 0 :(得分:0)

也许,那样?但我并没有看出你用“我做了什么”做了什么。没有地方去的地方或多个地方的行。如果事情会变得更加简单,那么事情就会变得更加简单。行被命令。

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)

答案 1 :(得分:0)

作为IMO,检查我将使用onyl var1的位置的两个变量是不可能的/ neseccary。

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值小于&#34; i&#34;使用first的值。最后使用gr更新排列向量ifelse并进行排列。