Есть ли в R конструкция, подобная «выходу»?

#arrays #r #for-loop

#массивы #r #для цикла

Вопрос:

Я вроде как новичок в R и только начал использовать его для построения некоторых графиков.

У меня есть этот код:

 times=integer(nrow(df));
for(i in 1:nrow(df)) {
  time=df[i 1,4]-df[i,4];
  times[i]<-time
}
 

Должен быть более умный способ сделать это без предварительной инициализации, не так ли?
Я не уверен, но то, что я ищу, это что-то вроде:

 times <- for(i in 1:nrow(df)) yield df[i 1,4]-df[i,4]
 

(Я знаю, что это недопустимый код :))
Я надеюсь, что этот вопрос еще не задан. Я искал и не нашел ничего конкретного по «выходу» и инициализации массивов.

Как и было запрошено….

Образец данных в df:

 7926 08:00:27:ed:f3:e5 MESSAGEHANDLER START 1.319242e 12
7927 08:00:27:ed:f3:e5 MESSAGEHANDLER   END 1.319242e 12
7928 08:00:27:ed:f3:e5 MESSAGEHANDLER START 1.319242e 12
7929 08:00:27:ed:f3:e5 MESSAGEHANDLER   END 1.319242e 12
7930 08:00:27:ed:f3:e5 MESSAGEHANDLER START 1.319242e 12
7931 08:00:27:ed:f3:e5 MESSAGEHANDLER   END 1.319242e 12
7932 08:00:27:ed:f3:e5 MESSAGEHANDLER START 1.319242e 12
7933 08:00:27:ed:f3:e5 MESSAGEHANDLER   END 1.319242e 12
7934 08:00:27:ed:f3:e5 MESSAGEHANDLER START 1.319242e 12
7935 08:00:27:ed:f3:e5 MESSAGEHANDLER   END 1.319242e 12
7936 08:00:27:ed:f3:e5 MESSAGEHANDLER START 1.319242e 12
7937 08:00:27:ed:f3:e5 MESSAGEHANDLER   END 1.319242e 12
7938 08:00:27:ed:f3:e5 MESSAGEHANDLER START 1.319242e 12
7939 08:00:27:ed:f3:e5 MESSAGEHANDLER   END 1.319242e 12
 

После того, как мой цикл раз равен:

 [7921] 508 500 497 501 466 502 505 500 488 501 500 501 490 501 478 501 501 501
[7939]  NA
 

Хорошо, чтобы получить более конкретную информацию, я действительно хочу сделать это:

 times1=integer(nrow(df));for(i in 1:nrow(df)) { if (df[i,3] == "START") times1[i]<-df[i 1,4]-df[i,4]}
times2=integer(nrow(df));for(i in 1:nrow(df)) { if (df[i,3] == "END") times2[i]<-df[i 1,4]-df[i,4]}
 

Тогда результат будет примерно таким, как для times1:

 [7921]   0 500   0 501   0 502   0 500   0 501   0 501   0 501   0 501   0 501
[7939]   0
 

Но мне нужно:

 [3960]   500   501   502   500   501   501   501   501   501
 

Словами:

Я анализирую измеренные данные из файла csv, который попадает в df, как показано выше. Это для «START», за которым следует «END»

Данные в df описывают, что пакет был получен, когда в df [,3] есть «ЗАПУСК» в определенное время в миллисекундах в df [,4]. Теперь мне нужно вычислить время, прошедшее от получения до отправки (это время, необходимое моей машине для анализа ПОЛУЧЕННОГО ПАКЕТА и вычисления результата для его ОТПРАВКИ.) Так что КОНЕЦ в df[,3] означает, что пакет был успешно отправлен в unixtime df[,4] .

Другой случай — «END», за которым следует «START»

Это время, которое прошло между «мой пакет был отправлен» и «был получен» новый.

Теперь я добавляю образец csv и мой полный код для воспроизведения:

 #load csv in df!
df = read.csv("/tmp/measure.csv",FALSE)
absolute=integer(nrow(df));for(i in 1:nrow(df)) {time=df[i,4]-df[1,4];absolute[i]<-(time/1000)}
times=integer(nrow(df));for(i in 1:nrow(df)) {time=df[i 1,4]-df[i,4];times[i]<-time}
#plot(absolute,times)
plot(absolute,times,lty=1,pch=1,col="#11223399",type="l")
lines(absolute,array(mean(times,na.rm=1),nrow(df)),col="red")
 

Вот мой measure.csv:

 08:00:27:ed:f3:e5,TMCMESSAGEHANDLER,END,1319238175202
08:00:27:ed:f3:e5,TMCMESSAGEHANDLER,START,1319238175690
08:00:27:ed:f3:e5,TMCMESSAGEHANDLER,END,1319238176195
08:00:27:ed:f3:e5,TMCMESSAGEHANDLER,START,1319238176665
08:00:27:ed:f3:e5,TMCMESSAGEHANDLER,END,1319238177167
08:00:27:ed:f3:e5,TMCMESSAGEHANDLER,START,1319238177669
08:00:27:ed:f3:e5,TMCMESSAGEHANDLER,END,1319238178172
08:00:27:ed:f3:e5,TMCMESSAGEHANDLER,START,1319238178639
08:00:27:ed:f3:e5,TMCMESSAGEHANDLER,END,1319238179139
08:00:27:ed:f3:e5,TMCMESSAGEHANDLER,START,1319238179658
08:00:27:ed:f3:e5,TMCMESSAGEHANDLER,END,1319238180161
08:00:27:ed:f3:e5,TMCMESSAGEHANDLER,START,1319238180654
08:00:27:ed:f3:e5,TMCMESSAGEHANDLER,END,1319238181154
08:00:27:ed:f3:e5,TMCMESSAGEHANDLER,START,1319238181669
08:00:27:ed:f3:e5,TMCMESSAGEHANDLER,END,1319238182170
08:00:27:ed:f3:e5,TMCMESSAGEHANDLER,START,1319238182629
08:00:27:ed:f3:e5,TMCMESSAGEHANDLER,END,1319238183130
 

Я надеюсь, что это делает его более понятным.

Комментарии:

1. Вам будет намного легче понять, что вы хотите, если вы опубликуете образцы данных и ожидаемые результаты.

2. дело не в результате, они просто прекрасны. Это все о том, что может язык. Но я публикую некоторые из своих данных. Итак, мой код работает, но выглядит неуклюже.

3. @Andrie: я не могу использовать diff, потому что мне нужно выполнить дополнительные проверки типа if (df[i,3] == START amp;amp; df[i 1,3] == END) сделайте это иначе, сделайте это

4. Извините, но я понятия не имею, что вы пытаетесь сделать. Кажется, вы выполняете какую-то операцию над вектором. Может быть, это поможет, если вы 1) опишите словами, что должна делать эта операция, и 2) сделайте свой пример минимально воспроизводимым.

5. Одно предостережение: поступают ли сообщения в последовательном порядке? Если пакеты перекрываются, вам нужно разделить по идентификатору пакета.

Ответ №1:

Я думаю, вы хотите вычислить разницу между последовательными элементами в векторе. В этом случае вы ищете diff :

 set.seed(0)
x <- sample(1:10, 5)

x
[1] 1 2 9 5 3

diff(x)
[1]  1  7 -4 -2
 

Ответ №2:

Надеюсь, я не слишком далек от истины — почему бы вообще не избежать цикла?:

     # generate some data sort of similar to yours:
    DF <- data.frame(pos4 = rep(c("START","END"),10),times=rep(0,20))
    DF$times[DF$pos4=="START"] <- 1:10
    DF$times[DF$pos4=="END"] <- DF$times[DF$pos4=="START"] runif(10)
    DF
    DF
        pos4 times
    1  START  1.000000
    2    END  1.750459
    3  START  2.000000
    4    END  2.212599
    5  START  3.000000
    6    END  3.974809
    ....
 

Я предполагаю, что время НАЧАЛА и ОКОНЧАНИЯ в вашем наборе данных в порядке..

     (times <- DF$times[DF$pos4=="END"] - DF$times[DF$pos4=="START"]) 
    [1] 0.7504590 0.2125986 0.9748094 0.3313644 0.3448410 0.8677022 0.9534317
    [8] 0.1279304 0.6500212 0.1798664
 

не уверен, какие проверки вам нужно выполнить, поскольку они не были в цикле for, который вы опубликовали в вопросе.

——————РЕДАКТИРОВАТЬ—————————

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

     DIFFS <- diff(DF$times)
 

дает вам все различия, вы просто хотели разделить это на два объекта: один для четных индексов, другой для нечетных индексов:

     times1 <- DIFFS[seq(from=1,to=length(DIFFS),by=2)]
    times2 <- DIFFS[seq(from=2,to=length(DIFFS),by=2)]
 

и не связанная, но тоже полезная: вы использовали ‘absolute’ и ‘df’ для имен объектов в вашем коде, но это также функции в R, поэтому, хотя это работает, лучше присвоить им имена, которые еще не приняты. Рад, что вы получили то, что искали!

Комментарии:

1. это почти то, что я ищу. В настоящее время я тестирую.

2. хорошо, это отлично работает для вычисления разницы с 1,2 3,4 5,6, но как мне вычислить 2,3 и 4,5? я только заставляю его вычислять 2,1 4,3 6,5 (мне нужен следующий ЗАПУСК, а не предыдущий). Извините, понятно, что я имею в виду? 🙂

3. Чтобы добавить к этому evildead, R сильно отличается от других языков, к которым вы, возможно, привыкли. Циклы используются редко. Циклы в R намного медленнее, чем другие методы, которые могут быть вам доступны.

4. Я уверен, что вообще не использую циклы. Я читал, что R похож на диалект scheme, так что это имеет смысл. Обычно в «функциональных языках» у вас есть что-то вроде так называемого «for expression» с выходом (по крайней мере, в scala и python). Почему я использовал реальный цикл в первую очередь, потому что мне нужно обратиться к «следующему» элементу из относительной позиции. В настоящее время проблема с опубликованным выражением заключается в том, что оно принимает первое найденное, а затем выполняет итерацию по коллекции.

5. затем выполните diff(), как говорит Андри, для ваших первых различий (END1-START1): diff(DF $times)[seq(from=1,to=length(DF $ times),by= 2)] и для ваших различий второго типа (START2-END1): diff(DF $ раз)[seq(от= 2, до = длина (DF $ раз), by= 2)]

Ответ №3:

Вы также можете сделать что-то вроде

 lapply(sequence(nrow(df)-1),function(i,df) df[i 1,4]-df[i,4],df)
 

или также попробуйте sapply вместо lapply (в противном случае, тот же синтаксис).

Редактировать:

Более конкретно, я думаю

 times <- sapply(sequence(nrow(df)-1),function(i,df) df[i 1,4]-df[i,4],df)
 

или

 times <- unlist(lapply(sequence(nrow(df)-1),function(i,df) df[i 1,4]-df[i,4],df))
 

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

 times <- apply(matrix(df[,4],ncol=2,byrow=TRUE),1,diff)
 

Ответ №4:

Я выхожу за дверь, но 2 комментария: 1) добавьте заголовки столбцов во фрейм данных 2) Я думаю, что оператору нужен пакет reshape, чтобы разделить его время начала и окончания на 2 разных столбца, называемых start, а затем end. затем используйте операцию End-Start для вектора.

Комментарии:

1. Ответ Тима Риффа мне нравится больше, чем мой собственный. Это быстрее.

2. Я согласен — изменение формы фрейма данных упростило бы задачу