Управление матрицей с условиями и объединение результатов - PullRequest
0 голосов
/ 28 января 2020

У меня есть матрица 8x8 с городами и их расстояниями друг от друга, как показано ниже:

+--------------+------+--------+------+--------------+---------+------+------+----------+
|              | NYC  | BOSTON |  DC  | PHILADELPHIA | CHICAGO |  SF  |  LA  | SAN JOSE |
+--------------+------+--------+------+--------------+---------+------+------+----------+
| NYC          |    0 |    200 |  300 |          500 |     600 | 1500 | 1800 |     2000 |
| BOSTON       |  200 |      0 |  300 |          200 |     700 | 1600 | 1900 |     2100 |
| DC           |  300 |    300 |    0 |          250 |     550 | 1400 | 1850 |     2200 |
| PHILADELPHIA |  500 |    200 |  250 |            0 |     650 | 1300 | 1700 |     1900 |
| CHICAGO      |  600 |    700 |  550 |          650 |       0 | 1250 | 1600 |     1500 |
| SF           | 1500 |   1600 | 1400 |         1300 |    1250 |    0 |  300 |      400 |
| LA           | 1800 |   1900 | 1850 |         1700 |    1600 |  300 |    0 |      250 |
| SAN JOSE     | 2000 |   2100 | 2200 |         1900 |    1500 |  400 |  250 |        0 |
+--------------+------+--------+------+--------------+---------+------+------+----------+

Я пытаюсь отфильтровать комбинации, где расстояние больше 500, и затем объединить результаты как показано ниже:

+--------------+---------------------------+---------------+
|     FROM     |            TO             |   DISTANCE    |
+--------------+---------------------------+---------------+
| NYC          | BOSTON, DC, PHILADELPHIA  | 200, 300, 500 |
| BOSTON       | NYC,DC, PHILADELPHIA      | 200, 300, 200 |
| DC           | NYC, BOSTON, PHILADELPHIA |  300,300, 250 |
| PHILADELPHIA | NYC,BOSTON, DC            | 500, 200, 250 |
| CHICAGO      |                           |               |
| SF           | LA, SAN JOSE              |      300, 400 |
| LA           | SF, SAN JOSE              |      300, 250 |
| SAN JOSE     | SF, LA                    |      400, 250 |
+--------------+---------------------------+---------------+

Я нашел похожий пример здесь:

https://stackoverflow.com/questions/20210787/r-getting-the-minimum-value-for-each-row-in-a-matrix-and-returning-the-row-and/20214579#20214579

, и я знаю, что могу объединить, используя функцию агрегирования

Я нашел пригодный для использования решение, но мне было интересно, если есть простой способ достичь этого

Ниже мое решение:

result <- t(sapply(seq(nrow(X)), function(i) {
  j <- which.min(X[i,])
  c(paste(rownames(X)[i], colnames(X)[j], sep='/////'), X[i,j])
}))

a<-data.frame(do.call('rbind', strsplit(as.character(result$col1),'/////',fixed=TRUE)), result$col2)

Ответы [ 2 ]

1 голос
/ 28 января 2020

Здесь то же самое с другим решением R:

res <- apply(df, 1, function(x) {
  data.frame(
    from = names(df)[x == 0], 
    to = paste0(names(df)[x <= 500 & x > 0], collapse = ", "),
    dist = paste0(x[x <= 500 & x > 0], collapse = ", ")
  )
})

do.call(rbind, res)

Что приводит к

#                     from                        to          dist
# NYC                   NYC  BOSTON, DC, PHILADELPHIA 200, 300, 500
# BOSTON             BOSTON     NYC, DC, PHILADELPHIA 200, 300, 200
# DC                     DC NYC, BOSTON, PHILADELPHIA 300, 300, 250
# PHILADELPHIA PHILADELPHIA           NYC, BOSTON, DC 500, 200, 250
# CHICAGO           CHICAGO                                        
# SF                     SF               LA, SANJOSE      300, 400
# LA                     LA               SF, SANJOSE      300, 250
# SANJOSE           SANJOSE                    SF, LA      400, 250
1 голос
/ 28 января 2020

Используя dplyr, мы можем получить данные в длинном формате, выбрать строки с расстоянием менее 500 и суммировать значения для каждого города.

library(dplyr)

df %>%
  rownames_to_column('from') %>%
  tidyr::pivot_longer(cols = -from) %>%
  filter(value <= 500 & from != name) %>%
  group_by(from) %>%
  summarise(to = toString(name), 
            distance = toString(value))

# A tibble: 7 x 3
#  from         to                        distance     
#  <chr>        <chr>                     <chr>        
#1 BOSTON       NYC, DC, PHILADELPHIA     200, 300, 200
#2 DC           NYC, BOSTON, PHILADELPHIA 300, 300, 250
#3 LA           SF, SANJOSE               300, 250     
#4 NYC          BOSTON, DC, PHILADELPHIA  200, 300, 500
#5 PHILADELPHIA NYC, BOSTON, DC           500, 200, 250
#6 SANJOSE      SF, LA                    400, 250     
#7 SF           LA, SANJOSE               300, 400     

данные

df <- structure(list(NYC = c(0L, 200L, 300L, 500L, 600L, 1500L, 1800L, 
2000L), BOSTON = c(200L, 0L, 300L, 200L, 700L, 1600L, 1900L, 
2100L), DC = c(300L, 300L, 0L, 250L, 550L, 1400L, 1850L, 2200L
), PHILADELPHIA = c(500L, 200L, 250L, 0L, 650L, 1300L, 1700L, 
1900L), CHICAGO = c(600L, 700L, 550L, 650L, 0L, 1250L, 1600L, 
1500L), SF = c(1500L, 1600L, 1400L, 1300L, 1250L, 0L, 300L, 400L
), LA = c(1800L, 1900L, 1850L, 1700L, 1600L, 300L, 0L, 250L), 
SANJOSE = c(2000L, 2100L, 2200L, 1900L, 1500L, 400L, 250L, 
0L)), row.names = c("NYC", "BOSTON", "DC", "PHILADELPHIA", 
"CHICAGO", "SF", "LA", "SANJOSE"), class = "data.frame")
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...