Есть ли более быстрый способ преобразовать список координат в массив в R? - PullRequest
2 голосов
/ 10 марта 2020

Я относительно новичок в R. У меня есть большой список координат вокселей (> 1 Гбайт), который я прочитал из файла дампа LAMMPS и имеет такую ​​структуру (это небольшой воспроизводимый пример):

> lammps_file
V1  V2 V3 V4 V5
1  78  1  1  1
2 163  2  1  1
3 157  3  1  1
4  79  4  1  1
5 238  1  2  1
6 145  2  2  1
7 103  3  2  1
8 108  4  2  1
9 254  1  3  1
10  85  2  3  1
11 219  3  3  1
12 214  4  3  1
13 109  1  4  1
14 237  2  4  1
15 145  3  4  1
16 118  4  4  1
17  28  1  1  2
18 134  2  1  2
19 174  3  1  2
20   2  4  1  2
21 210  1  2  2
22 219  2  2  2
23 138  3  2  2
24 219  4  2  2
25 231  1  3  2
26  53  2  3  2
27 255  3  3  2
28 255  4  3  2
29 157  1  4  2
30 188  2  4  2
31 143  3  4  2
32  85  4  4  2
33  71  1  1  3
34  80  2  1  3
35 164  3  1  3
36 142  4  1  3
37 144  1  2  3
38 194  2  2  3
39 173  3  2  3
40  55  4  2  3
41 115  1  3  3
42   9  2  3  3
43  45  3  3  3
44 103  4  3  3
45  53  1  4  3
46  87  2  4  3
47  37  3  4  3
48  88  4  4  3
49 176  1  1  4
50 127  2  1  4
51   7  3  1  4
52 123  4  1  4
53  97  1  2  4
54   5  2  2  4
55 216  3  2  4
56  37  4  2  4
57  52  1  3  4
58  50  2  3  4
59  63  3  3  4
60 231  4  3  4
61 164  1  4  4
62 101  2  4  4
63 137  3  4  4
64 197  4  4  4

с координатами вокселей x, y и z в столбцах 3: 5 и значением интенсивности вокселей в столбце 2. Столбец 1 не используется. Моя цель - записать в массив значения интенсивности вокселей всех (n) координат xyz. Я делаю это, чтобы использовать структуру массива и легко преобразовать ее в стек tiff-изображений (с EBImage) ... Для этой цели я использую следующий код

> lcoordinates <- read.table(lammps_file, ...)
> n <- dim(lcoordinates)

> varray <- array(0, c(number_voxels_in_x, number_voxels_in_y, number_voxels_in_z))
>
>   for (j in 1:n[1]) {
>        v <-  as.numeric(lcoordinates[j,2:5])
>        varray[v[2], v[3], v[4]] <- v[1]
>   }

Результат должен выглядеть следующим образом:

> varray

, , 1

     [,1] [,2] [,3] [,4]
[1,]   78  238  254  109
[2,]  163  145   85  237
[3,]  157  103  219  145
[4,]   79  108  214  118

, , 2

     [,1] [,2] [,3] [,4]
[1,]   28  210  231  157
[2,]  134  219   53  188
[3,]  174  138  255  143
[4,]    2  219  255   85

, , 3

     [,1] [,2] [,3] [,4]
[1,]   71  144  115   53
[2,]   80  194    9   87
[3,]  164  173   45   37
[4,]  142   55  103   88

, , 4

     [,1] [,2] [,3] [,4]
[1,]  176   97   52  164
[2,]  127    5   50  101
[3,]    7  216   63  137
[4,]  123   37  231  197

Это работает, но занимает огромное количество времени (> 3 часа для 1 * 10 ^ 9 вокселей или строк). Есть ли способ кодировать это быстрее? Спасибо!

Ответы [ 2 ]

0 голосов
/ 11 марта 2020

Если ваши данные уже упорядочены в том порядке, в котором они должны быть, то, безусловно, самый быстрый способ - использовать dim<-. В вашем примере:

## sort into correct order (maybe this already happened)
lammps_file <- lammps_file[order(lammps_file$V3,lammps_file$V4,lammps_file$V5)]
## create a new vector
y <- lammps_file$V2
## now just assign it a dimension
dim(y) <- c(n1,n2,n3)

(если ваш массив выходит транспонированным, вам могут понадобиться V3, V4 и V5 в другом порядке, но подход будет работать). Установка атрибута dim имеет незначительные вычислительные затраты независимо от размера данных. В вашем примере огромные затраты, потому что вы перебираете строки. В R зацикливание строк набора данных почти никогда не является самым быстрым способом решения проблемы, вместо этого следует использовать векторы.

0 голосов
/ 11 марта 2020

Вы можете использовать матричный индекс для поднабора, например:

varray <- array(0, c(max(lcoordinates[,3]), max(lcoordinates[,4])
   , max(lcoordinates[,5])))
varray[as.matrix(lcoordinates[3:5])] <- lcoordinates[,2]
varray
, , 1

     [,1] [,2] [,3] [,4]
[1,]   78  238  254  109
[2,]  163  145   85  237
[3,]  157  103  219  145
[4,]   79  108  214  118

, , 2

     [,1] [,2] [,3] [,4]
[1,]   28  210  231  157
[2,]  134  219   53  188
[3,]  174  138  255  143
[4,]    2  219  255   85

, , 3

     [,1] [,2] [,3] [,4]
[1,]   71  144  115   53
[2,]   80  194    9   87
[3,]  164  173   45   37
[4,]  142   55  103   88

, , 4

     [,1] [,2] [,3] [,4]
[1,]  176   97   52  164
[2,]  127    5   50  101
[3,]    7  216   63  137
[4,]  123   37  231  197

В случае, если это уже правильно отсортировано @MrFlick ответ в комментарии быстрее.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...