Как я могу изначально хранить шестиугольные сетки в R?

Если я хочу сохранить некоторую квадратную сетку в R, это легко сделать.

Сказать,

|    | 0    | 1     | 2     |
|----|------|-------|-------|
| 0  | TRUE | TRUE  | FALSE |
| 1  | NA   | FALSE | TRUE  |
| 2  | TRUE | TRUE  | FALSE |

хранится как декартова система координат

m <- matrix(data = c(TRUE, TRUE, FALSE, NA, FALSE, TRUE, TRUE, TRUE, FALSE), nrow = 3, ncol = 3, byrow = FALSE)

и существующие методы и математика работают так, как ожидалось:

apply(X = m, MARGIN = 2, FUN = "sum")
# [1]  2 NA  2
print(m)
#      [,1]  [,2]  [,3]
#[1,]  TRUE    NA  TRUE
#[2,]  TRUE FALSE  TRUE
#[3,] FALSE  TRUE FALSE

(Я знаю, что могу также reshape2::melt преобразовать это в длинную форму, но мне нравится широкая, потому что так выглядит пользовательский интерфейс).

Пока все хорошо, знакомо, интуитивно понятно.


Теперь введите шестиугольную сетку.

какая-то сетка

Из замечательного/авторитетного введения Амита Пателя в шестигранные сетки я понял, что действительно должен сохранять такие сетка с использованием кубической системы координат, как в приведенном выше примере, поскольку в противном случае (= с двумерными декартовыми координатами плюс смещения) операции линейной алгебры больше не работают, и возникает общая грубость кода. Я понимаю (думаю).

Система координат куба

(Для получения дополнительной информации, опять же, см. фантастический объяснитель Амита Пателя).

Ввод этих данных в широкой форме через array() кажется совершенно безумным, потому что многие ячейки даже не существуют (а NA уже используется). Итак, я ввожу/сохраняю это в длинной форме, например:

df <- rbind(c(1, 0, -1, FALSE), 
        c(0, 1, -1, NA),
        c(1, -1, 0, TRUE),
        c(0, 0, 0, TRUE),
        c(-1, 1, 0, FALSE),
        c(0, -1, 1, NA),
        c(-1, 0, 1, TRUE))
colnames(df) <- c("y", "x", "z", "value")
df
#      y  x  z value
#[1,]  1  0 -1     0
#[2,]  0  1 -1    NA
#[3,]  1 -1  0     1
#[4,]  0  0  0     1
#[5,] -1  1  0     0
#[6,]  0 -1  1    NA
#[7,] -1  0  1     1

В этом кадре данных есть все данные, но он никак не «знает», что x, y и z являются диагональными координатами.

Как я могу:

  1. сохранить это в широкой форме, где я могу легко использовать линейную и матричную алгебру,
  2. использовать установленные методы (скажем, colSums() или apply())
  3. а также удобно print примерно так:

скриншот

(SE даже не будет правильно выделять эту напечатанную шестнадцатеричную сетку, отсюда и скриншот.)

Короче говоря, каким будет элегантный/рекомендуемый/канонический способ "нативного" хранения такой шестиугольной сетки в R?

Я смутно осознаю, что, вероятно, мог бы реализовать для этого свой собственный S3 OO, хотя я надеялся, что это может уже существовать в той или иной форме. Я действительно нашел множество пакетов, выполняющих шестнадцатеричное биннинг непрерывных данных, но они, похоже, не имели дело с хранением шестнадцатеричных сеток или по крайней мере, не подвергать эти внутренности.


person maxheld    schedule 20.04.2017    source источник


Ответы (1)


<сильный>1. сохранить это в расширенной форме, где я могу легко использовать линейную и матричную алгебру

Вероятно, осевые координаты, упомянутые в http://www.redblobgames.com/grids/hexagons/#coordinates — лучший выбор. Это может дать возможность преобразовать в стандартную ij-матрицу с i=x и j=y, вам просто нужно указать, что поместить в ячейки матрицы, которые не покрыты вашей шестнадцатеричной сеткой (ваша собственная "NA" ). Затем вы можете работать с измерениями x и y, как обычно, и иметь матрицу только с пустыми треугольными верхним правым и нижним левым треугольниками. (Это не сумасшествие, а естественный способ. В лучшем случае вам придется найти другое решение для вашего NA в ваших данных. Извините, что не возился с кодом для вашего примера.)

<сильный>2. используйте установленные методы (скажем, colSums() или apply())

С помощью пакета dplyr вы можете

df %>% as_data_frame() %>% group_by(x) %>% summarize(sum(value))

суммировать для фиксированного x или тому подобного.

<сильный>3. а также удобно распечатать

У меня нет решения для печати, но отображение меток с помощью ggplot2 может быть решением.

df %>% as_data_frame() %>% ggplot(aes(x=x+0.5*y, y=y, label=value)) + geom_text()

Примечания: Представленный здесь результат представляет собой перевернутую версию того, что вы хотели напечатать, но я надеюсь, что вы сможете найти правильный переворот самостоятельно. x=x+0.5*y служит здесь, чтобы дать вам гексагональную форму, к которой вы стремитесь. С x=x у вас просто косой шестиугольник.

Короче говоря, каким был бы элегантный/рекомендуемый/канонический способ "естественного" хранения такой шестиугольной сетки в R?

Вы уже нашли это. Для вычислений вы используете свой df. Для хранения немного эффективнее использовать осевой. Вы можете легко извлечь координату z обратно.

person janlo    schedule 21.04.2017