R: Ускорить цикл for для очень большого кадра данных? - PullRequest
0 голосов
/ 21 сентября 2018

У меня есть огромный набор координат с соответствующими Z-значениями.Некоторые из пар координат повторяются несколько раз с разными значениями Z.Я хочу получить среднее значение всех Z-значений для каждой уникальной пары координат.

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

Вот как выглядит мой df:

> df
           x        y         Z                                 xy
1  -54.60417 4.845833 0.3272980 -54.6041666666667/4.84583333333333
2  -54.59583 4.845833 0.4401644 -54.5958333333333/4.84583333333333
3  -54.58750 4.845833 0.5788663          -54.5875/4.84583333333333
4  -54.57917 4.845833 0.6611844 -54.5791666666667/4.84583333333333
5  -54.57083 4.845833 0.7830828 -54.5708333333333/4.84583333333333
6  -54.56250 4.845833 0.8340629          -54.5625/4.84583333333333
7  -54.55417 4.845833 0.8373666 -54.5541666666667/4.84583333333333
8  -54.54583 4.845833 0.8290986 -54.5458333333333/4.84583333333333
9  -54.57917 4.845833 0.9535526 -54.5791666666667/4.84583333333333
10 -54.59583 4.837500 0.0000000           -54.5958333333333/4.8375
11 -54.58750 4.845833 0.8582580          -54.5875/4.84583333333333
12 -54.58750 4.845833 0.3857006          -54.5875/4.84583333333333

Вы можете видеть, что некоторые координаты xyодинаковы (например, строки 3,11,12 или 4 и 9), и я хочу, чтобы средние значения Z всех этих идентичных координат.Итак, вот мой сценарий:

mean<-vector(mode = "numeric",length = length(df$x))

for (i in 1:length(df$x)){
  mean(df$Z[which(df$xy==df$xy[i])])->mean[i]
} 
mean->df$mean
df<-df[,-(3:4)]
df<-unique(df)

И я получаю что-то вроде этого:

> df
           x        y      mean
1  -54.60417 4.845833 0.3272980
2  -54.59583 4.845833 0.4401644
3  -54.58750 4.845833 0.6076083
4  -54.57917 4.845833 0.8073685
5  -54.57083 4.845833 0.7830828
6  -54.56250 4.845833 0.8340629
7  -54.55417 4.845833 0.8373666
8  -54.54583 4.845833 0.8290986
10 -54.59583 4.837500 0.0000000

Это работает, но, безусловно, есть способ ускорить этот процесс (возможно, безцикл for) для df с гораздо большим числом строк?

Ответы [ 2 ]

0 голосов
/ 21 сентября 2018

Добро пожаловать!В будущем было бы лучше предложить нам быстрый способ скопировать и вставить некоторый код, который генерирует основные функции набора данных, с которым вы работаете.Вот пример, который я думаю:

DF <- data.frame(x = sample(c(-54.1, -54.2), size = 10, replace = TRUE),
                 y = sample(c(4.8, 4.4), size = 10, replace = TRUE),
                 z = runif(10))

Это выглядит как комбинированный подход с применением разделения:

set.seed(1)
df <- data.frame(x = sample(c(-54.1, -54.2), size = 10, replace = TRUE),
                 y = sample(c(4.8, 4.4), size = 10, replace = TRUE),
                 z = runif(10))

library(data.table)
DT <- as.data.table(df)
DT[, .(mean_z = mean(z)), keyby = c("x", "y")]
#>        x   y    mean_z
#> 1: -54.2 4.4 0.3491507
#> 2: -54.2 4.8 0.4604533
#> 3: -54.1 4.4 0.3037848
#> 4: -54.1 4.8 0.5734239

library(dplyr)
#> 
#> Attaching package: 'dplyr'
#> The following objects are masked from 'package:data.table':
#> 
#>     between, first, last
#> The following objects are masked from 'package:stats':
#> 
#>     filter, lag
#> The following objects are masked from 'package:base':
#> 
#>     intersect, setdiff, setequal, union
df %>%
  group_by(x, y) %>%
  summarise(mean_z = mean(z))
#> # A tibble: 4 x 3
#> # Groups:   x [?]
#>       x     y mean_z
#>   <dbl> <dbl>  <dbl>
#> 1 -54.2   4.4  0.349
#> 2 -54.2   4.8  0.460
#> 3 -54.1   4.4  0.304
#> 4 -54.1   4.8  0.573

Создано в 2018-09-21 представьте пакет (v0.2.1)

0 голосов
/ 21 сентября 2018

Вы можете попробовать dplyr::summarise.

library(dplyr)
df %>%
  group_by(x, y) %>%
  summarise(meanZ = mean(Z))

Я думаю, это займет меньше минуты, в зависимости от вашей машины.

Кто-то другой может предоставить data.tableответ, который может быть еще быстрее.

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