Re: [R] Method Guidance
Dear Jeff, I am sending an updated version of the code. The initial version assumed that the time points correspond to an integer sequence. The code would fail for arbitrary times. The new code is robust. I still assume that the data is in column-format and that you want the time to the previous "A"-event, even if there are other non-A events in between. The code is similar, but we cannot use seq(0, x-1) anymore. Instead, we will repeat the time point of the previous A-event. (Last-A Carried forward) # jrdf = the data frame from my previous mail; cumEvent = cumsum(jrdf$Event_A); # we cannot use the actual values of the cumsum, # but will use the number of (same) values to the previous event; freqEvent = rle(cumEvent); freqEvent = freqEvent$lengths; # repeat the time-points timesA = jrdf$Time[jrdf$Event_A == 1]; sameTime = rep(timesA, freqEvent); timeToA = jrdf$Time - sameTime; ### Step 2: # extract/view the times (as before); timeToA[jrdf$Event_B >= 1]; # Every Time to A: e.g. for multiple extractions; cbind(jrdf, timeToA); # Time to A only for B: set non-B to 0; # Note: - the rle() function might be less known; - it is "equivalent" to: tbl = table(cumEvent); # to be on the safe side (as the cumsum is increasing): id = order(as.numeric(names(tbl))); tbl = tbl[id]; Hope this helps, Leonard On 1/14/2022 3:30 AM, Leonard Mada wrote: Dear Jeff, My answer is a little bit late, but I hope it helps. jrdf = read.table(text="Time Event_A Event_B Lag_B 1 1 1 0 2 0 1 1 3 0 0 0 4 1 0 0 5 0 1 1 6 0 0 0 7 0 1 3 8 1 1 0 9 0 0 0 10 0 1 2", header=TRUE, stringsAsFactors=FALSE) Assuming that: - Time, Event_A, Event_B are given; - Lag_B needs to be computed; Step 1: - compute time to previous Event A; tmp = jrdf[, c(1,2)]; # add an extra event so last rows are not lost: tmp = rbind(tmp, c(nrow(tmp) + 1, 1)); timeBetweenA = diff(tmp$Time[tmp$Event_A > 0]); timeToA = unlist(sapply(timeBetweenA, function(x) seq(0, x-1))) ### Step 2: # - extract the times; timeToA[jrdf$Event_B >= 1]; cbind(jrdf, timeToA); Sincerely, Leonard __ R-help@r-project.org mailing list -- To UNSUBSCRIBE and more, see https://stat.ethz.ch/mailman/listinfo/r-help PLEASE do read the posting guide http://www.R-project.org/posting-guide.html and provide commented, minimal, self-contained, reproducible code.
Re: [R] Method Guidance
Suppose your data were represented as parallel vectors "time" and "type", meaning that at time[i] a type[i] event occurred. You didn't say what you wanted if there were a run of "A" or "B". If you are looking for the time span between the last of a run of one sort of event and the first of a run of the other sort of event then the following can be used. f <- function(time, type, fromType, toType) { # return times of (fromTime) last of a run of 'fromType' and # (toTime) first of subsequent run of 'toType for each such transition. stopifnot(length(time)==length(type), !anyNA(type), !anyNA(time), !is.unsorted(time), length(fromType)==1, length(toType)==1) i <- seq_len(length(time)-1) iBeforeChange <- which((type[i] == fromType) & (type[i+1] == toType)) data.frame(fromTime=time[iBeforeChange], toTime=time[iBeforeChange+1L]) } E.g., > d <- data.frame(time=c(101,102,102,105,107,111,115), type=c("A","A","B","A","B","B","A")) > d time type 1 101A 2 102A 3 102B 4 105A 5 107B 6 111B 7 115A > f(time=d$time, type=d$type, fromType="A", toType="B") fromTime toTime 1 102102 2 105107 > with(.Last.value, toTime - fromTime) [1] 0 2 > f(time=d$time, type=d$type, fromType="B", toType="A") fromTime toTime 1 102105 2 111115 > with(.Last.value, toTime - fromTime) [1] 3 4 With the dplyr package you can avoid the index 'i' by using lag() inside of mutate(). E.g., > d |> mutate(AtoB = (lag(type)=="A" & type=="B")) time type AtoB 1 101A FALSE 2 102A FALSE 3 102B TRUE 4 105A FALSE 5 107B TRUE 6 111B FALSE 7 115A FALSE -Bill On Tue, Jan 11, 2022 at 4:56 PM Jeff Reichman wrote: > R-Help Forum > > > > Looking for a little guidance. Have an issue were I'm trying to determine > the time between when Event A happened(In days) to when a subsequent Event > B > happens. For Example at Time 1 Evat A happens and subsequently Event B > happens at the same day (0) and the next day (1) then Event A happens again > at time 4 and Event B happens the next day and 3 days later so on and so > forth. I gather there is no function that will do that so I suspect I will > need to grate so sour of do while loop? Any suggestions? > > > > > > Time Event_A Event_B Time_B > > 1 1 1 > 0 > > 2 0 1 > 1 > > 3 0 0 > 0 > > 4 1 0 > 0 > > 5 0 1 > 1 > > 6 0 0 > 0 > > 7 0 1 > 3 > > 8 1 1 > 0 > > 9 0 0 > 0 > > 10 0 1 > 2 > > > > > Jeff Reichman > > > [[alternative HTML version deleted]] > > __ > R-help@r-project.org mailing list -- To UNSUBSCRIBE and more, see > https://stat.ethz.ch/mailman/listinfo/r-help > PLEASE do read the posting guide > http://www.R-project.org/posting-guide.html > and provide commented, minimal, self-contained, reproducible code. > [[alternative HTML version deleted]] __ R-help@r-project.org mailing list -- To UNSUBSCRIBE and more, see https://stat.ethz.ch/mailman/listinfo/r-help PLEASE do read the posting guide http://www.R-project.org/posting-guide.html and provide commented, minimal, self-contained, reproducible code.
Re: [R] Method Guidance
Dear Jeff, My answer is a little bit late, but I hope it helps. jrdf = read.table(text="Time Event_AEvent_B Lag_B 1 1 10 2 0 11 3 0 00 4 1 00 5 0 11 6 0 00 7 0 13 8 1 10 9 0 00 10 0 12", header=TRUE, stringsAsFactors=FALSE) Assuming that: - Time, Event_A, Event_B are given; - Lag_B needs to be computed; Step 1: - compute time to previous Event A; tmp = jrdf[, c(1,2)]; # add an extra event so last rows are not lost: tmp = rbind(tmp, c(nrow(tmp) + 1, 1)); timeBetweenA = diff(tmp$Time[tmp$Event_A > 0]); timeToA = unlist(sapply(timeBetweenA, function(x) seq(0, x-1))) ### Step 2: # - extract the times; timeToA[jrdf$Event_B >= 1]; cbind(jrdf, timeToA); Sincerely, Leonard __ R-help@r-project.org mailing list -- To UNSUBSCRIBE and more, see https://stat.ethz.ch/mailman/listinfo/r-help PLEASE do read the posting guide http://www.R-project.org/posting-guide.html and provide commented, minimal, self-contained, reproducible code.
Re: [R] Method Guidance
To be fair, Jim, when people stop and think carefully before sending a message to a forum like this, and then explain their situation and request carefully and in enough detail, often a solution comes to them and they can abort sending! Yes, the question asked is a bit vague. Other than asking for more details, the answers would also tend to be vague, or completely mysterious. Someone sent a pointer to a web page that may well supply ideas to use, but maybe not as the question remains unclear. So here is my vague reply. You say you have data in what seems to be a data.frame that includes some events marked with a starting time and other related events with a starting/stopping time or something like that. You want in some way to line up two or more such related events so you can calculate something like time elapsed. I am not clear if these come in pairs or can be extended as in go from point A to B then C and so on. For some such things, a data.frame may not ultimately be the right data structure. So first you need to specify how to match things up. Is there another common field like StudentID that can be used to find all records showing when they began doing A or B? If not, how do you recognize what B goes with what A? The difference matters in terms of how to approach the problem. Once you show a small representative sample, maybe people can suggest approaches. I did not find your sample even slightly useful. Lots of 1 and 0 and maybe some wrapping lines. The overall approaches for doing what I hope you are doing, vary. You can of course go through the data row by row and look forward and do a calculation and print results. Or, you might want to reshape your data, perhaps merging subsets of the data with other subsets, to create new data where the start and stop segments are in the same row in multiple columns. The latter might be useful for all kinds of analyses including making graphs. Your example seems to suggest you have a variable that is focused on days so you have not shown some kind of date field. But do events always happen in subsequent days, like in a game of postal chess, or can it happen within a day, perhaps multiple times, like taking your dog for a walk? Can two events interweave or is there a guarantee that each event completes before the next round starts? Is your data in a specific time order so B always follows A? Many questions like the above matter in understanding your purpose and goal and then seeing what algorithm will take the data you start with and do something. If organized in certain ways and with no errors, it may be trivial. If not, in some cases it simply is not doable. And in some cases, such as buying and selling shares of stock, you have interesting things like rules of what happens if you buy back shares within a month or so as to whether you adjust the basis and of course the length of time can determine capital gains rates. More complexity is whether you have to do some kind of averaging or FIFO or can designate which shares. Now this may have nothing to do with your application, but is an example of why some problems may better be treated differently than others. -Original Message- From: Jim Lemon To: Jeff Newmiller Cc: r-help mailing list Sent: Wed, Jan 12, 2022 1:44 am Subject: Re: [R] Method Guidance Hi Jeff, A completely obscure question deserves a completely obscure answer: jrdf<-read.table(text="Time Event_A Event_B Lag_B 1 1 1 0 2 0 1 1 3 0 0 0 4 1 0 0 5 0 1 1 6 0 0 0 7 0 1 3 8 1 1 0 9 0 0 0 10 0 1 2", header=TRUE,stringsAsFactors=FALSE) plot(jrdf$Time-0.2,jrdf$Event_A,type="p", xlim=c(1,12),ylim=c(0.9,1.1), xlab="Day",ylab="",main="The As and the Bs", pch=c(" ","A")[jrdf$Event_A+1],yaxt="n") points(jrdf$Time+jrdf$Lag_B+0.2,jrdf$Event_B,pch=c(" ","B")[jrdf$Event_B+1]) Jim On Wed, Jan 12, 2022 at 1:33 PM Jeff Newmiller wrote: > > 1) Figure out how to post plain text please. What you saw is not what we see. > > 2) I see a "table" of input information but no specific expectation of what > would come out of this hypothetical function. > > 3) Maybe you will find something relevant in this blog post: > https://jdnewmil.github.io/blog/post/cumsum-and-diff-tricks/ > > ps not sure what "grate so sour" was supposed to be. > > pps While loops are not necessarily evil. > > On January 11, 2022 4:56:20 PM PST, Jeff Reichman > wrote: > >R-Help Forum > > > > > > > >Looking for a little guidance. Have an issue were I'm trying to determine > >the time between when Event A happened
Re: [R] Method Guidance
Rui Well that certainly is a lot more straight forward than the direction I was trying and you have introduced me to a couple of new functions. Thank you Jeff -Original Message- From: Rui Barradas Sent: Wednesday, January 12, 2022 5:08 AM To: reichm...@sbcglobal.net; r-help@r-project.org Subject: Re: [R] Method Guidance Hello, Here is a base R solution for what I understand of the question. It involves ave and cumsum. cumsum of the values of Event_A breaks Event_B in segments and ave applies a function to each segment. To find where are the times B, coerce to logical and have which() take care of it. Data in dput format at the end. ave(as.logical(df1$Event_B), cumsum(df1$Event_A), FUN = function(x) { y <- integer(length(x)) y[x] <- which(x) - 1L y }) #[1] 0 1 0 0 1 0 3 0 0 2 More readable, with an auxiliary function. aux_fun <- function(x) { y <- integer(length(x)) y[x] <- which(x) - 1L y } ave(as.logical(df1$Event_B), cumsum(df1$Event_A), FUN = aux_fun) #[1] 0 1 0 0 1 0 3 0 0 2 Now assign this result to a df1 column. Here I just test for equality. new <- ave(as.logical(df1$Event_B), cumsum(df1$Event_A), FUN = aux_fun) identical(new, df1$Time_B) #[1] TRUE # Data df1 <- structure(list(Time = 1:10, Event_A = c(1L, 0L, 0L, 1L, 0L, 0L, 0L, 1L, 0L, 0L), Event_B = c(1L, 1L, 0L, 0L, 1L, 0L, 1L, 1L, 0L, 1L), Time_B = c(0L, 1L, 0L, 0L, 1L, 0L, 3L, 0L, 0L, 2L)), class = "data.frame", row.names = c(NA, -10L)) Hope this helps, Rui Barradas Às 00:56 de 12/01/22, Jeff Reichman escreveu: > R-Help Forum > > > > Looking for a little guidance. Have an issue were I'm trying to > determine the time between when Event A happened(In days) to when a > subsequent Event B happens. For Example at Time 1 Evat A happens and > subsequently Event B happens at the same day (0) and the next day (1) > then Event A happens again at time 4 and Event B happens the next day > and 3 days later so on and so forth. I gather there is no function > that will do that so I suspect I will need to grate so sour of do while loop? > Any suggestions? > > > > > > Time Event_A Event_B Time_B > > 1 1 1 > 0 > > 2 0 1 > 1 > > 3 0 0 > 0 > > 4 1 0 > 0 > > 5 0 1 > 1 > > 6 0 0 > 0 > > 7 0 1 > 3 > > 8 1 1 > 0 > > 9 0 0 > 0 > > 10 0 1 2 > > > > > Jeff Reichman > > > [[alternative HTML version deleted]] > > __ > R-help@r-project.org mailing list -- To UNSUBSCRIBE and more, see > https://stat.ethz.ch/mailman/listinfo/r-help > PLEASE do read the posting guide > http://www.R-project.org/posting-guide.html > and provide commented, minimal, self-contained, reproducible code. > __ R-help@r-project.org mailing list -- To UNSUBSCRIBE and more, see https://stat.ethz.ch/mailman/listinfo/r-help PLEASE do read the posting guide http://www.R-project.org/posting-guide.html and provide commented, minimal, self-contained, reproducible code.
Re: [R] Method Guidance
Hello, Here is a base R solution for what I understand of the question. It involves ave and cumsum. cumsum of the values of Event_A breaks Event_B in segments and ave applies a function to each segment. To find where are the times B, coerce to logical and have which() take care of it. Data in dput format at the end. ave(as.logical(df1$Event_B), cumsum(df1$Event_A), FUN = function(x) { y <- integer(length(x)) y[x] <- which(x) - 1L y }) #[1] 0 1 0 0 1 0 3 0 0 2 More readable, with an auxiliary function. aux_fun <- function(x) { y <- integer(length(x)) y[x] <- which(x) - 1L y } ave(as.logical(df1$Event_B), cumsum(df1$Event_A), FUN = aux_fun) #[1] 0 1 0 0 1 0 3 0 0 2 Now assign this result to a df1 column. Here I just test for equality. new <- ave(as.logical(df1$Event_B), cumsum(df1$Event_A), FUN = aux_fun) identical(new, df1$Time_B) #[1] TRUE # Data df1 <- structure(list(Time = 1:10, Event_A = c(1L, 0L, 0L, 1L, 0L, 0L, 0L, 1L, 0L, 0L), Event_B = c(1L, 1L, 0L, 0L, 1L, 0L, 1L, 1L, 0L, 1L), Time_B = c(0L, 1L, 0L, 0L, 1L, 0L, 3L, 0L, 0L, 2L)), class = "data.frame", row.names = c(NA, -10L)) Hope this helps, Rui Barradas Às 00:56 de 12/01/22, Jeff Reichman escreveu: R-Help Forum Looking for a little guidance. Have an issue were I'm trying to determine the time between when Event A happened(In days) to when a subsequent Event B happens. For Example at Time 1 Evat A happens and subsequently Event B happens at the same day (0) and the next day (1) then Event A happens again at time 4 and Event B happens the next day and 3 days later so on and so forth. I gather there is no function that will do that so I suspect I will need to grate so sour of do while loop? Any suggestions? Time Event_A Event_B Time_B 1 1 1 0 2 0 1 1 3 0 0 0 4 1 0 0 5 0 1 1 6 0 0 0 7 0 1 3 8 1 1 0 9 0 0 0 10 0 1 2 Jeff Reichman [[alternative HTML version deleted]] __ R-help@r-project.org mailing list -- To UNSUBSCRIBE and more, see https://stat.ethz.ch/mailman/listinfo/r-help PLEASE do read the posting guide http://www.R-project.org/posting-guide.html and provide commented, minimal, self-contained, reproducible code. __ R-help@r-project.org mailing list -- To UNSUBSCRIBE and more, see https://stat.ethz.ch/mailman/listinfo/r-help PLEASE do read the posting guide http://www.R-project.org/posting-guide.html and provide commented, minimal, self-contained, reproducible code.
Re: [R] Method Guidance
Hi Jeff, A completely obscure question deserves a completely obscure answer: jrdf<-read.table(text="Time Event_AEvent_B Lag_B 1 1 10 2 0 11 3 0 00 4 1 00 5 0 11 6 0 00 7 0 13 8 1 10 9 0 00 10 0 12", header=TRUE,stringsAsFactors=FALSE) plot(jrdf$Time-0.2,jrdf$Event_A,type="p", xlim=c(1,12),ylim=c(0.9,1.1), xlab="Day",ylab="",main="The As and the Bs", pch=c(" ","A")[jrdf$Event_A+1],yaxt="n") points(jrdf$Time+jrdf$Lag_B+0.2,jrdf$Event_B,pch=c(" ","B")[jrdf$Event_B+1]) Jim On Wed, Jan 12, 2022 at 1:33 PM Jeff Newmiller wrote: > > 1) Figure out how to post plain text please. What you saw is not what we see. > > 2) I see a "table" of input information but no specific expectation of what > would come out of this hypothetical function. > > 3) Maybe you will find something relevant in this blog post: > https://jdnewmil.github.io/blog/post/cumsum-and-diff-tricks/ > > ps not sure what "grate so sour" was supposed to be. > > pps While loops are not necessarily evil. > > On January 11, 2022 4:56:20 PM PST, Jeff Reichman > wrote: > >R-Help Forum > > > > > > > >Looking for a little guidance. Have an issue were I'm trying to determine > >the time between when Event A happened(In days) to when a subsequent Event B > >happens. For Example at Time 1 Evat A happens and subsequently Event B > >happens at the same day (0) and the next day (1) then Event A happens again > >at time 4 and Event B happens the next day and 3 days later so on and so > >forth. I gather there is no function that will do that so I suspect I will > >need to grate so sour of do while loop? Any suggestions? > > > > > > > > > > > >Time Event_A Event_B Time_B > > > >1 1 1 > >0 > > > >2 0 1 > >1 > > > >3 0 0 > >0 > > > >4 1 0 > >0 > > > >5 0 1 > >1 > > > >6 0 0 > >0 > > > >7 0 1 > >3 > > > >8 1 1 > >0 > > > >9 0 0 > >0 > > > >10 0 1 2 > > > > > > > > > >Jeff Reichman > > > > > > [[alternative HTML version deleted]] > > > >__ > >R-help@r-project.org mailing list -- To UNSUBSCRIBE and more, see > >https://stat.ethz.ch/mailman/listinfo/r-help > >PLEASE do read the posting guide http://www.R-project.org/posting-guide.html > >and provide commented, minimal, self-contained, reproducible code. > > -- > Sent from my phone. Please excuse my brevity. > > __ > R-help@r-project.org mailing list -- To UNSUBSCRIBE and more, see > https://stat.ethz.ch/mailman/listinfo/r-help > PLEASE do read the posting guide http://www.R-project.org/posting-guide.html > and provide commented, minimal, self-contained, reproducible code. __ R-help@r-project.org mailing list -- To UNSUBSCRIBE and more, see https://stat.ethz.ch/mailman/listinfo/r-help PLEASE do read the posting guide http://www.R-project.org/posting-guide.html and provide commented, minimal, self-contained, reproducible code.
Re: [R] Method Guidance
1) Figure out how to post plain text please. What you saw is not what we see. 2) I see a "table" of input information but no specific expectation of what would come out of this hypothetical function. 3) Maybe you will find something relevant in this blog post: https://jdnewmil.github.io/blog/post/cumsum-and-diff-tricks/ ps not sure what "grate so sour" was supposed to be. pps While loops are not necessarily evil. On January 11, 2022 4:56:20 PM PST, Jeff Reichman wrote: >R-Help Forum > > > >Looking for a little guidance. Have an issue were I'm trying to determine >the time between when Event A happened(In days) to when a subsequent Event B >happens. For Example at Time 1 Evat A happens and subsequently Event B >happens at the same day (0) and the next day (1) then Event A happens again >at time 4 and Event B happens the next day and 3 days later so on and so >forth. I gather there is no function that will do that so I suspect I will >need to grate so sour of do while loop? Any suggestions? > > > > > >Time Event_A Event_B Time_B > >1 1 1 >0 > >2 0 1 >1 > >3 0 0 >0 > >4 1 0 >0 > >5 0 1 >1 > >6 0 0 >0 > >7 0 1 >3 > >8 1 1 >0 > >9 0 0 >0 > >10 0 1 2 > > > > >Jeff Reichman > > > [[alternative HTML version deleted]] > >__ >R-help@r-project.org mailing list -- To UNSUBSCRIBE and more, see >https://stat.ethz.ch/mailman/listinfo/r-help >PLEASE do read the posting guide http://www.R-project.org/posting-guide.html >and provide commented, minimal, self-contained, reproducible code. -- Sent from my phone. Please excuse my brevity. __ R-help@r-project.org mailing list -- To UNSUBSCRIBE and more, see https://stat.ethz.ch/mailman/listinfo/r-help PLEASE do read the posting guide http://www.R-project.org/posting-guide.html and provide commented, minimal, self-contained, reproducible code.
[R] Method Guidance
R-Help Forum Looking for a little guidance. Have an issue were I'm trying to determine the time between when Event A happened(In days) to when a subsequent Event B happens. For Example at Time 1 Evat A happens and subsequently Event B happens at the same day (0) and the next day (1) then Event A happens again at time 4 and Event B happens the next day and 3 days later so on and so forth. I gather there is no function that will do that so I suspect I will need to grate so sour of do while loop? Any suggestions? Time Event_A Event_B Time_B 1 1 1 0 2 0 1 1 3 0 0 0 4 1 0 0 5 0 1 1 6 0 0 0 7 0 1 3 8 1 1 0 9 0 0 0 10 0 1 2 Jeff Reichman [[alternative HTML version deleted]] __ R-help@r-project.org mailing list -- To UNSUBSCRIBE and more, see https://stat.ethz.ch/mailman/listinfo/r-help PLEASE do read the posting guide http://www.R-project.org/posting-guide.html and provide commented, minimal, self-contained, reproducible code.