Нахождение количества единиц, соединенных с 5 или более другими единицами (например, соседями) в ряде файлов CSV - PullRequest
0 голосов
/ 28 октября 2019

Я написал нижеприведенную функцию, чтобы найти число 1 с одним подключенным другим 1.

temp <- list.files(pattern="*.csv")
files <- lapply(temp, read.table)

number_1_neighbour <- function(x) { 
   check_diff <- diff(x) == 0
   (c(0,check_diff) + c(check_diff,0)) * x 
}

neigh1_rows_columns <- lapply(files, function(y) sum(t(apply(y, 1, 
number_1_neighbour)) + apply(y, 2, number_1_neighbour) == 1))

Как мне обновить этот код, чтобы проверять наличие 1 с 5 или более подключенными 1?

Например, в такой матрице, как ...

0 0 0 0 0 0 0 0 0 0
1 1 1 0 0 0 0 0 1 1
1 1 1 0 0 0 0 0 0 0 
0 0 0 0 1 1 1 0 0 0
0 0 0 0 1 1 1 1 0 0

Было бы 4 1, соединенных 5 или более другими 1 как соседями.

Воспроизводимый пример,

set.seed(99) 
mat <- matrix(sample(c(0,1), 2500, prob=c(0.8,0.2), replace=TRUE), nrow=50)
mat

set.seed(1234)
mat2 <- matrix(sample(c(0,1), 2500, prob=c(0.8,0.2), replace=TRUE), nrow=50)
mat2

set.seed(9999)
mat3 <- matrix(sample(c(0,1), 2500, prob=c(0.8,0.2), replace=TRUE), nrow=50)
mat3

list <- list(mat, mat2, mat3)

number_1_neighbour <- function(x) { 
  check_diff <- diff(x) == 0
  (c(0,check_diff) + c(check_diff,0)) * x
}

# Using function number_1_neighbour over rows and columns to get the number of neighbours in 2 directions that have exactly 1 neighbour.
neigh1_rows_columns <- lapply(list, function(y) sum(t(apply(y, 1, number_1_neighbour)) + apply(y, 2, number_1_neighbour) >= 5))
neigh1_rows_columns

Это выводит как 0, поскольку он смотрит только в 4 направлениях, поэтому мне нужно иметь возможность смотреть и в диагональных направлениях.

1 Ответ

0 голосов
/ 30 октября 2019

Я буду использовать небольшую матрицу 3x3 для иллюстрации метода.

m <- matrix(c(0, 0, 1, 1, 1, 1, 1, 1, 0), nrow = 3)
m
#>      [,1] [,2] [,3]
#> [1,]    0    1    1
#> [2,]    0    1    1
#> [3,]    1    1    0

Мы будем использовать пакет matrixcalc, в частности его функции shift.* для вычисления количества 1-соседейкаждой клетки. Например, давайте посмотрим на shif.up(m).

library(matrixcalc)
m_u <- shift.up(m)
m_u
#>      [,1] [,2] [,3]
#> [1,]    0    1    1
#> [2,]    1    1    0
#> [3,]    0    0    0

Это просто m, поднятый вверх с нижним рядом, заполненным нулями. Основная идея здесь заключается в том, что для любых заданных индексов (i, j), если матрица m_u имеет 1 в этом месте, это означает, что эта ячейка в исходной матрице имеет 1 -конечность внизу. Аналогичная логика применима ко всем другим сменам. Итак, чтобы вычислить число 1 соседей во всех 8 направлениях, мы должны суммировать все 8 сдвиговых матриц.

mat_neighbours <- function(m) {
  # up, down, left, right shifts
  m_u <- shift.up(m)
  m_d <- shift.down(m)
  m_l <- shift.left(m)
  m_r <- shift.right(m)

  # diagonal shifts
  m_ul <- shift.left(m_u)
  m_ur <- shift.right(m_u)
  m_dl <- shift.left(m_d)
  m_dr <- shift.right(m_d)

  m_u + m_d + m_l + m_r +
  m_ul + m_ur + m_dl + m_dr
}

mat_neighbours(m)
#>      [,1] [,2] [,3]
#> [1,]    2    3    3
#> [2,]    4    5    4
#> [3,]    2    3    3

Здесь мы можем видеть, например, что ячейка (2, 2) в m имеет 5 1 соседей.

Имея эту функцию, теперь легко вычислить количество 1 ячеек с 5 или более 1 соседями.

sum((m == 1) & mat_neighbours(m) >= 5)
#> [1] 1

Чтобы применить его к вашему списку файлов:

library(purrr)
temp %>% 
  map(read.table) %>% 
  map(as.matrix) %>% 
  map_dbl(~sum((. == 1) & mat_neighbours(.) >= 5))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...