-2

(EDIT: одна из проблем здесь - масштаб, а именно то, что работает для одной строки, взорвет/сработает R на кадре данных 200 000 * 50. Например , strptime необходимо применять по столбцам, а не по ряду причин, чтобы избежать зависания. Я ищу решения для рабочего кода, которые вы на самом деле выполняли на 200 000 * 50, включая измеренное время выполнения, а не просто случайное «это просто», замечание. Легко получить время автономной работы> 12 часов, если вы выберете неправильный fn. Затем я также попросил вас сделать код настройки нулевого времени быстрее, работа еще не закончена до тех пор, пока это не сделано. Пока никто не пытался это сделать.)Как векторизовать и ускорять преобразование времени в стеке() в кадре данных


Хочу Vectorize и ускорить следующее многостадийное преобразование логарифмический время, с точностью до миллисекунд, с участием преобразования strtime() к одному числовому, с последующим вычитанием, а затем log() на большом данными кадра (200000 строк * 300 смещ_по_столбцы; другие (не время) столбцы опущены). Код ниже. Так же, как и его векторизация и быстрый, дополнительная проблема заключается в том, что я не уверен, как лучше всего представлять промежуточные значения (более высокие) на каждом этапе, например. как список из strtime, matrix, vector). Я уже пытался apply,sapply,lapply,vapply,ddply::maply(),... но несовместимость промежуточного формата (ов) продолжает баловаться меня ...

Каждая строка содержит 50 столбцов time1..time50 (CHR, формат = "HH: MM: SS. sss "), представляющий время как строку в миллисекундном разрешении. Мне нужна точность в миллисекундах. В каждой строке столбцы time1..time50 находятся в неуклонном порядке, и я хочу преобразовать их в журнал времени до time50. Преобразование fn parse_hhmmsecms() находится в нижней части и требует серьезной векторизации и ускорения, вы можете видеть, что альтернативные версии прокомментированы. То, что я понял до сих пор: strtime() быстрее, чем (Multiple) substr() звонков, я затем преобразовать как-то список из трех числовых (hh,mm,sec.ms), а затем преобразовать в вектор предполагая, следующий шаг должен быть вектор-кратно с %*% c(3600,60,1) для преобразования в числовые секунды. Вот псевдокод того, что я делаю для каждой строки, и каждую временную строку; Полный код находится в нижней части:

for each row in dataframe { # vectorize this, loop_apply(), or whatever... 
#for each time-column index i ('time1'..'time50') { # vectorize this... 
hhmmsecms_50 <- parse_hhmmsecms(xx$time50[i]) 
# Main computation 
xx[i,Clogtime] <- -10*log10(1000*(hhmmsecms_50 - parse_hhmmsecms(xx[i,Ctime]))) 
# Minor task: fix up all the 'zero-time' events to be evenly spaced between -3..0 
#} 
} 

Так есть пять подзадач участвующих:

  1. Как векторизации обработки списка возвращенное strtime()? так как он возвращает список из 3 элементов, когда передается 2D-фрейм или 1-я строка строк времени, мы получим трехмерный или 2D-промежуточный объект. (0) ID:
  2. Как векторизовать функцию целиком? parse_hhmmsecms()? Что такое HTML, xHTML, WML?
  3. Затем сделать вычитание и войти
  4. Vectorize код FixUp нулевого времени, а также (теперь это самая медленная часть далеко)
  5. Как ускорить шаги 1 ... 4.?

Фрагмент кода ниже, используя десять примеров столбцов time41..50 (используйте random_hhmmsecms() если вы хотите большего размера образца)

Я сделал все возможное, чтобы следовать these recommendations, это, как воспроизводимый как я могу получить его в шестичасовая работа:

# Each of 200,000 rows has 50 time strings (chr) like this...  
xx <- structure(list(time41 = c("08:00:41.465", "08:00:50.573", "08:00:50.684" 
), time42 = c("08:00:41.465", "08:00:50.573", "08:00:50.759"), 
    time43 = c("08:00:41.465", "08:00:50.573", "08:00:50.759" 
    ), time44 = c("08:00:41.465", "08:00:50.664", "08:00:50.759" 
    ), time45 = c("08:00:41.465", "08:00:50.684", "08:00:50.759" 
    ), time46 = c("08:00:42.496", "08:00:50.684", "08:00:50.759" 
    ), time47 = c("08:00:42.564", "08:00:50.759", "08:00:51.373" 
    ), time48 = c("08:00:48.370", "08:00:50.759", "08:00:51.373" 
    ), time49 = c("08:00:50.573", "08:00:50.759", "08:00:54.452" 
    ), time50 = c("08:00:50.573", "08:00:50.759", "08:00:54.452" 
    )), .Names = c("time41", "time42", "time43", "time44", "time45", 
"time46", "time47", "time48", "time49", "time50"), row.names = 3:5, class = "data.frame") 

# Handle millisecond timing and time conversion 
options('digits.secs'=3) 

# Parse "HH:MM:SS.sss" timestring into (numeric) number of seconds (Very slow) 
parse_hhmmsecms <- function(t) { 
    as.numeric(substr(t,1,2))*3600 + as.numeric(substr(t,4,5))*60 + as.numeric(substr(t,7,12)) # WORKS, V SLOW 

    #c(3600,60,1) %*% sapply((strsplit(t[1,]$time1, ':')), as.numeric) # SLOW, NOT VECTOR 

    #as.vector(as.numeric(unlist(strsplit(t,':',fixed=TRUE)))) %*% c(3600,60,1) # WANT TO VECTORIZE THIS 
} 

random_hhmmsecms <- function(n=1, min=8*3600, max=16*3600) { 
# Generate n random hhmmsecms objects between min and max (8am:4pm) 
xx <- runif(n,min,max) 
ss <- xx %% 60 
mm <- (xx %/% 60) %% 60 
hh <- xx %/% 3600 
sprintf("%02d:%02d:%05.3f", hh,mm,ss) 
} 

xx$logtime45 <- xx$logtime44 <- xx$logtime43 <- xx$logtime42 <- xx$logtime41 <- NA 
xx$logtime50 <- xx$logtime49 <- xx$logtime48 <- xx$logtime47 <- xx$logtime46 <- NA 

# (we pass index vectors as the dataframe column ordering may change) 
Ctime <- which(colnames(xx)=='time41') : which(colnames(xx)=='time50') 
Clogtime <- which(colnames(xx)=='logtime41') : which(colnames(xx)=='logtime50') 
for (i in 40:nrow(xx)) { 
    #if (i%%100==0) { print(paste('... row',i)) } 

    hhmmsecms_50 <- parse_hhmmsecms(xx$time50[i]) 
    xx[i,Clogtime] <- -10*log10(1000*(hhmmsecms_50 - parse_hhmmsecms(xx[i,Ctime]))) 

    # Now fix up all the 'zero-time' events to be evenly spaced between -3..0 
    Czerotime.p <- which(xx[i,Clogtime]==Inf | xx[i,Clogtime]>-1e-9) 
    xx[i,Czerotime.p] <- seq(-3,0,length.out=length(Czerotime.p)) 
} 
+0

Посмотрите на векторизованную встроенную функцию strptime и связанные классы POSICct и POSIXlt. Вы можете применить strptime к вектору и преобразовать его в числовой. Есть много встроенных функций обработки времени. – John

+0

Джон, нет, я пробовал это несколько недель назад, * 'as.POSIXlt()' * конверсия отбрасывает миллисекунды (chron и zoo выглядят одинаково непригодными). – smci

+0

В первой попытке поиска Google я нашел [this] (http://stackoverflow.com/questions/2150138/how-to-parse-milliseconds-in-r). (Фактически это был первый результат.) – joran

ответ

2

Возможно, вы можете быть слишком сложными.

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

  1. вам необходимо установить options("digits.secs"=7) (это максимум, который может быть отображен), чтобы увидеть они отображались

  2. вам нужен дополнительный характер синтаксического анализа для strptime и др

Все это в документах и ​​бесчисленных примерах здесь, на SO.

Быстрые примеры:

R> someTime <- ISOdatetime(2011, 12, 27, 2, 3, 4.567) 
R> someTime 
[1] "2011-12-27 02:03:04.567 CST" 
R> now <- Sys.time() 
R> now 
[1] "2011-12-27 16:48:20.247298 CST"  # microsecond display on Linux 
R> 
R> txt <- "2001-02-03 04:05:06.789123" 
R> strptime(txt, "%Y-%m-%d %H:%M:%OS") # note the %0S for sub-seconds 
[1] "2001-02-03 04:05:06.789123" 
R> 

И ключевые функции, такие как strptime или as.POSIXct все vectorised и вы можете бросить целые колонны на них.

+0

спасибо, но набор данных приходит как csv, если вы читаете в датах и ​​делаете strptime в colClasses, я, кажется, вспоминаю, что он сильно взрывает память. Я повторю его в кусочки. Вторая причина нежелательно хранить время с поддельной датой, например. «2001-02-03» - это то, что я печатаю их, сравниваю их (< > ==), манипулируя ими, объединяю их, использую их в виде графиков или меток гистограммы и т. Д. Но да, я могу использовать * 'as.numeric (strptime (...) - origin_date) '* – smci

+0

Вы * можете * и возможно * должны * делать арифметические действия в классах' Date' и 'POSIXct'. Если у вас есть только часы: mins: secs, возможно, добавьте их на номинальную базовую дату 2001-01-01 или что-то в этом роде. Проблема с памятью известна, что, к сожалению, это цена, которую мы должны заплатить за общее удобство использования 'strptime'. –

+0

Код исправления с нулевым временем теперь является медленной частью, не могли бы вы также обратиться к этому вопросу? Выполнение привязки нулевого времени по строке занимает> 12 часов.Пожалуйста, опубликуйте свое фактическое время выполнения на 200 000 * 50 фреймов данных или аналогичных. – smci