2017-02-20 11 views
2

У меня есть большой набор данных, который я пытаюсь манипулировать с помощью dplyr. Для моей задачи перебора данных требуется манипуляция строк строки.Как ускорить работу на уровне строк с помощью dplyr

Я использую функцию по умолчанию rowwise(), и код работает. Однако для завершения операции требуется много времени.

VR_vehicle_GPSLocation = c("12.36556|0.74518153|xxxxxxxxxx", 
     "-51.75810|165.55526|xxxxxxxxxx", 
     "GPS nicht verfügbar", 
     "48.77410|171.08364|xxxxxxxxxx", 
     "GPS Not Available", 
     "0|0|N/R", 
     "32.18661| 170.56615|xxxxxxxxxx") 
df = data.frame(VR_vehicle_GPSLocation) 

jobs_location <- df %>% 
    rowwise() %>% 
    mutate(latitude = as.numeric(unlist(strsplit(as.character(VR_vehicle_GPSLocation), split='\\|'))[1]), 
      longitude = as.numeric(unlist(strsplit(as.character(VR_vehicle_GPSLocation), split='\\|'))[2])) %>% 
    select(latitude, longitude) 

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

jobs_location <- jobs %>% 
    partition() %>% 
    rowwise() %>% 
    mutate(latitude = as.numeric(unlist(strsplit(as.character(VR_vehicle_GPSLocation), split='\\|'))[1]), 
     longitude = as.numeric(unlist(strsplit(as.character(VR_vehicle_GPSLocation), split='\\|'))[2])) %>% 
    collect() 
+1

Прежде всего, мы не имеем MWE, поэтому мы не можем реально помочь вам. Во-вторых, глядя на ваш код, я сомневаюсь, что вам нужно запустить 'strsplit' по строке. Вы, вероятно, могли бы легко сделать все это сразу, используя 'data.table :: tstrsplit'. В-третьих, если вам нужны быстрые расщепления, не используйте регулярное выражение и не запускайте 'as.charcter' за строку (дважды каждый раз!). то есть 'VR_vehicle_GPSLocation' должен быть уже символом перед началом работы, а вместо' '\\ | '' использовать '|' в сочетании с 'fixed = TRUE'. Но снова мы нуждаемся в MWE. –

+0

Спасибо @DavidArenburg Я занят созданием примера, так что это будет иметь больше смысла. – Michael

+1

'library (data.table); setDT (df) [grep ("|", VR_vehicle_GPSLocation, fixed = TRUE), c ("широта", "долгота"): = tstrsplit (VR_vehicle_GPSLocation, "|", fixed = TRUE, keep = 1: 2, type. convert = TRUE)] 'и вам хорошо идти. –

ответ

2

к @DavidArenburg Все кредитные

Я подошел к проблеме с неэффективного углом. Использование векторизованного подхода явно улучшает производительность.

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

Наконец, важно отметить, что задача предварительной очистки необходимо обеспечить результирующее преобразование числовой (см комментарий Дэвида для более подробной информации)

library(dplyr) 
library(data.table) 
library(microbenchmark) 
library(ggplot2) 

mbm = microbenchmark(
    a = sample_n(jobs, 100) %>% 
    rowwise() %>% 
    mutate(latitude = as.numeric(unlist(strsplit(as.character(VR_vehicle_GPSLocation), split='\\|'))[1]), 
      longitude = as.numeric(unlist(strsplit(as.character(VR_vehicle_GPSLocation), split='\\|'))[2])), 

    b = setDT(sample_n(jobs, 100))[grep("|", VR_vehicle_GPSLocation, fixed = TRUE), 
        c("latitude", "longitude") := tstrsplit(VR_vehicle_GPSLocation, "|", fixed = TRUE, keep = 1:2, type.convert = TRUE)] 
) 

autoplot(mbm) 

картинка стоит тысячи слов

enter image description here


Еще одно предложение от Давида, чтобы преобразовать данные в числовой после tstrsplit. Я добавил две функции, которые выполняют преобразование в общих столбцах, и одну, которая применяет преобразование типа после разделения.

mbm = microbenchmark(
    a = sample_n(jobs, 100) %>% 
    rowwise() %>% 
    mutate(latitude = as.numeric(unlist(strsplit(as.character(VR_vehicle_GPSLocation), split='\\|'))[1]), 
      longitude = as.numeric(unlist(strsplit(as.character(VR_vehicle_GPSLocation), split='\\|'))[2])), 

    b = setDT(sample_n(jobs, 100))[grep("|", VR_vehicle_GPSLocation, fixed = TRUE), 
           c("latitude", "longitude") := tstrsplit(VR_vehicle_GPSLocation, "|", fixed = TRUE, keep = 1:2, type.convert = TRUE)], 

    c = sapply(setDT(sample_n(jobs, 100))[grep("|", VR_vehicle_GPSLocation, fixed = TRUE), 
           c("latitude", "longitude") := tstrsplit(VR_vehicle_GPSLocation, "|", fixed = TRUE, keep = 1:2)], as.numeric), 

    d = setDT(sample_n(jobs, 100))[grep("|", VR_vehicle_GPSLocation, fixed = TRUE), 
             c("latitude", "longitude") := lapply(tstrsplit(VR_vehicle_GPSLocation, "|", fixed = TRUE, keep = 1:2), as.numeric)] 
) 
autoplot(mbm) 

Последний вариант (d), безусловно, является победителем.

enter image description here

+1

Я думаю, что явное преобразование 'широты' и' longitude' в числовое число после расщепления вместо использования 'type.convert = TRUE' внутри' tstrsplit', вероятно, удвоит скорость. –

+0

Спасибо, @DavidArenburg - Я разработал пример немного больше на основе вашего предложения. – Michael