Re: [R] Method Guidance

2022-01-14 Thread Leonard Mada via R-help

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

2022-01-13 Thread Bill Dunlap
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

2022-01-13 Thread Leonard Mada via R-help

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

2022-01-12 Thread Avi Gross via R-help
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

2022-01-12 Thread Jeff Reichman
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

2022-01-12 Thread Rui Barradas

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

2022-01-11 Thread Jim Lemon
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

2022-01-11 Thread Jeff Newmiller
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

2022-01-11 Thread Jeff Reichman
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.