是否可以按之前的行中的值对数据框进行排序?

时间:2018-04-19 20:12:48

标签: r

我想按之前行中的值对数据框进行排序。这就是为什么 我有两列“startpoint”和“endpoint” 现在我想对行进行排序,以便每个具有特定“端点”的行后跟“startpoint”中具有相同值的行。

例如:

+------------+-----------+
| Startpoint | Endpoint  |
+------------+-----------+
| Berlin     | Munich    |
| Munich     | Paris     |
| Paris      | Barcelona |
| Barcelona  | Rom       |
+------------+-----------+

2 个答案:

答案 0 :(得分:0)

这是一个非常复杂的第一个解决方案,我欢迎尝试改进,因为我不太了解排序算法。我认为这也不适用于任何大型桌子,因为permutations的尺寸增加得太快(毕竟它是因素)。

我首先制作一个带有一些值列的重新排序版本,因为这可能是我们必须重新排列行的原因。首先获取所有潜在行顺序的列表。然后检查行以查看下一个start是否等于当前end,如果是,则将这些行保持在一起。过滤掉那些不具有这些行的行顺序,然后将表随机混洗到剩余的行顺序之一。当只剩下一个选项时停止。

这清楚地假设有一个独特的解决方案(实际上至少有两个解决方案,因为你可以反转这个顺序并满足条件,但是在一个随机选择的时候会随机选择)。

library(tidyverse)
library(arrangements)
set.seed(100)
tbl <- tibble(
  start = c("Berlin", "Munich", "Paris", "Barcelona"),
  end = c("Munich", "Paris", "Barcelona", "Rome"),
  val = rnorm(4)
) %>%
  slice(sample(1:nrow(.), nrow(.))) %>%
  rowid_to_column()
tbl
#> # A tibble: 4 x 4
#>   rowid start     end           val
#>   <int> <chr>     <chr>       <dbl>
#> 1     1 Paris     Barcelona -0.0789
#> 2     2 Berlin    Munich    -0.502 
#> 3     3 Munich    Paris      0.132 
#> 4     4 Barcelona Rome       0.887

row_orders <- permutations(nrow(tbl)) %>%
  as_tibble() %>%
  unite(order, remove = FALSE) %>%
  nest(-order) %>%
  mutate(data = map(data, as.integer))

sample_orders <- row_orders
sample_tbl <- tbl

while (nrow(sample_orders) > 1) {
  keep_together <- sample_tbl %>%
    mutate(
      nrc = lead(start) == end,
      nrc = replace_na(nrc, FALSE),
      cumsum = cumsum(lag(nrc, default = FALSE) == FALSE)
      ) %>%
    group_by(cumsum) %>%
    summarise(row_groups = str_c(rowid, collapse = "_")) %>%
    filter(str_length(row_groups) > 1) %>%
    `[[`("row_groups")
  sample_orders <- sample_orders %>%
    filter(str_detect(order, keep_together))
  sample_tbl <- tbl %>%
    slice(sample_orders$data[[sample(1:nrow(sample_tbl), 1)]])
}
#> Error in slice_impl(.data, dots): Evaluation error: subscript out of bounds.
print(sample_tbl)
#> # A tibble: 4 x 4
#>   rowid start     end           val
#>   <int> <chr>     <chr>       <dbl>
#> 1     2 Berlin    Munich    -0.502 
#> 2     3 Munich    Paris      0.132 
#> 3     1 Paris     Barcelona -0.0789
#> 4     4 Barcelona Rome       0.887

reprex package(v0.2.0)创建于2018-04-19。

答案 1 :(得分:0)

对于不遵循发布指南的操作答案,我有点矛盾,但我发现这是一个有趣的解决难题。

如果没有冲突,例如有多个航班(我认为他们是航班)与同一个出发地(或目的地),或者有一系列“往返”,在这种情况下你会跑进入无限循环,这是一个(有点令人惊讶的简单)解决方案。

flights <- read.table(sep = ",", stringsAsFactors = FALSE, header = TRUE, text = "
dep,arr
Montreal,Washington
Berlin,Munich
Miami,Paris
Munich,New York
Barcelona,Rome
New York,Montreal
Washington,Miami
Paris,Barcelona
")       

cont <- TRUE

while (cont) {
  # move down a flight for which the dep is an arr further down
  for (i in 1:(nrow(flights)-1)) {
    ind <- which(flights$arr == flights$dep[i])
    if (length(ind) == 0)  next
    if (ind > i) {
      flights <- flights[c(seq_len(i-1),
                           (i+1):ind,
                           i,
                           seq(from = ind + 1,
                               length.out = nrow(flights) - ind)),]
      break
    }
    cont <- FALSE
  }
}

结果

> flights
         dep        arr
2     Berlin     Munich
4     Munich   New York
6   New York   Montreal
1   Montreal Washington
7 Washington      Miami
3      Miami      Paris
8      Paris  Barcelona
5  Barcelona       Rome