Abigail575
Abigail575

Reputation: 175

Modifying a list based on the length of its shortest string

I have a list of two series that start out the same length. After executing the following code, the second series has one fewer elements than the first. Is there a general way of removing the final element of only the series containing n+1 elements, so that all the series in my list have n elements? What about if I have a combination of series in my list containing n, n+1 and n+2 elements? Below is a minimal reproducible example.

#test
library('urca')
tseries <- list("t1" = c(1,2,1,2,1,2,1,2,1,2,1,2,1,2,1), "t2" = c(1,2,3,4,5,6,7,8,9,10,9,8,7,8,9));

# apply stationarity test to the list of series
adf <- lapply(tseries, function(x) tseries::adf.test(x)$p.value)
adf

# index only series that need differencing
not_stationary <- tseries[which(adf > 0.05)]
stationary <- tseries[which(adf < 0.05)]
not_stationary <- lapply(not_stationary, diff);

# verify
adf <- lapply(not_stationary, function(x) tseries::adf.test(x)$p.value)
adf
now_stationary <- not_stationary

#combine stationary and now_stationary
tseries_diff <- c(stationary, now_stationary)
tseries_diff
#$t1
#[1] 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1

#$t2
#[1]  1  1  1  1  1  1  1  1  1 -1 -1 -1  1  1

So to summarise, I would ike to remove the final element, 1, from t1, but using code that can be applied to a list of series of lengths n and n+1 (and n+2 would be useful).

Thanks!

Upvotes: 0

Views: 249

Answers (2)

jessi
jessi

Reputation: 1518

Edited for list instead of vector - If you are dealing with list, you are wanting to make all of the series the length of the shortest:

(I modify the example to avoid using a library)

#test
mylist <- c(1,1,1,1,1)
mylongerlist <- c(1,1,1,1,1,1,1)
length(mylist)
# [1] 5
length(mylongerlist)
# [1] 7

#combine 
tseries_diff <- list("t1" = mylist, "t2" = mylongerlist)
tseries_diff
# $t1
# [1] 1 1 1 1 1
# 
# $t2
# [1] 1 1 1 1 1 1 1

# on the fly approach to truncate
lapply(tseries_diff, function(x) { length(x) <- min(lengths(tseries_diff)); x })
# $t1
# [1] 1 1 1 1 1
# 
# $t2
# [1] 1 1 1 1 1

And a function

# As a reusable function for clear code
reduceToShortestLength <- function(toCut) {
  # takes a list and cuts the tail off of any series longer than the shortest
  lapply(toCut, function(x) { length(x) <- min(lengths(tseries_diff)); x })
  }
reduceToShortestLength(tseries_diff)
# $t1
# [1] 1 1 1 1 1
# 
# $t2
# [1] 1 1 1 1 1

Original below (in case anyone thinks vector like I did at first) I think you are asking how to truncate a vector to the shortest length. The head function does this well in base R.

the on the fly approach:

> mylist <- c(1,1,1,1,1)
> mylongerlist <- c(1,1,1,1,1,1,1)
> length(mylist)
[1] 5
> length(mylongerlist)
[1] 7
> x <- head(mylongerlist, length(mylist))
> length(x)
[1] 5

A function can be written like so:

> reduceToShorterLength<- function(toshorten, template) { head(toshorten, length(template))}
> x <- reduceToShorterLength(mylongerlist, mylist)
> length(x)
[1] 5

Upvotes: 1

Sotos
Sotos

Reputation: 51592

You can find the minimum length and simply get the series up to that point, i.e.

new_series_list <- lapply(tseries_diff, function(i)i[seq(min(lengths(tseries_diff)))])

so the lengths are now the same

lengths(new_series_list)
#t1 t2 
#14 14 

This will work in any size series. It will trim the long series to much the short one.

Upvotes: 2

Related Questions