I am trying to understand the (to me) unexpected behavior of chaining seq and sort:
> seq(sort(c(5,1)))
[1] 1 2
> sort(c(5,1))
[1] 1 5
> seq(1,5)
[1] 1 2 3 4 5
> seq(c(sort(c(5,1))))
[1] 1 2
I would expect, that the first line yielded a sequence from 1 to 5, as this is what I would like to get, but I cannot make R do this just by chaining these to functions. Why?
If you are trying to pass arguments to a function as a vector , you can use do.call(). It allows you to execute a function call with a function name and a list of its arguments.
do.call(seq, as.list(sort(c(5,1)))) # vector needs to be converted to a list
#[1] 1 2 3 4 5
Your example returns [1] 1 2, because whenever we pass seq a vector of length > 1, it will act as seq_along. In other words, a sequence will be created with a length equal to the count of elements in the vector.
Related
This question already has answers here:
The difference between bracket [ ] and double bracket [[ ]] for accessing the elements of a list or dataframe
(11 answers)
Closed 2 years ago.
how to access elements from a vector that resides in a list
not clear why it works like in de code example
l[2] is a vector
l[2][1] is expected to refer to the 1st element of the vector
l <- list( 0, c(1,7,12))
l[2][1] # does not work, gives.....[1] 1 7 12
l[2][[1]][1] # does work as desired, gives [1] 1, but don no why
l[2][[1]][2] # gives [1] 7, as desired
Your can access it using l[[2]][1]
you can look at the output of l to see how items are organised. This can give you a clue as to how to call them
> l
[[1]]
[1] 0
[[2]]
[1] 1 7 12
In general, when you use the single bracket notation, R returns an element of the same class as the original object.
l is a list, so when you access an element of the list, e.g. l[2], R returns the element you asked for but wrapped in a list.
> l[2]
[[1]]
[1] 1 7 12
> class(l[2])
[1] "list"
If you want to "peel away" this layer, you use the double bracket syntax. R will then return the actual object at that index.
> l[[2]]
[1] 1 7 12
> class(l[[2]])
[1] "numeric"
Now you can access the elements of the vector.
> l[[2]][1]
[1] 1
> l[[2]][2]
[1] 7
If we use pluck, it is more easier
library(purrr)
pluck(l, 2, 1)
#[1] 1
I'd like to understand what's going on in this piece of R code I was testing. I'd like to replace part of a vector with another vector. The original and replacement values are in a data.frame. I'd like to replace all elements of the vector that match the original column with the corresponding replacement values. I have the answer to the larger question, but I'm unable to understand how it works.
Here's a simple example:
> vecA <- 1:5;
> vecB <- data.frame(orig=c(2,3), repl=c(22,33));
> vecA[vecA %in% vecB$orig] <- vecB$repl #Question-1
> vecA
[1] 1 22 33 4 5
> vecD<-data.frame(orig=c(5,7), repl=c(55,77))
> vecA[vecA %in% vecD$orig] <- vecD$repl #Question-2
Warning message:
In vecA[vecA %in% vecD$orig] <- vecD$repl :
number of items to replace is not a multiple of replacement length
> vecA
[1] 1 22 33 4 55
Here are my questions:
How does the assignment on Line-3 work? The LHS expression is a 2-item vector, whereas the RHS is a 5-element vector.
Why does the assignment on Line-6 give a warning (but still work)?
The First Question
R goes through each element in vecA and checks to see if it exists in vecB$orig. The %in% operator will return a boolean. If you run the command vecA %in% vecB$orig you get the following:
[1] FALSE TRUE TRUE FALSE FALSE
which is telling you that in the vector 1 2 3 4 5 it sees 2 and 3 in vecB$orig.
By subsetting vecA by this command, you are isolating only the TRUE values in vecA, so vecA[vecA %in% vecB$orig] returns:
[1] 2 3
On the RHS, you are re-assigning wherever vecA[vecA %in% vecB$orig] equals TRUE to vecB$repl, which will replace 2 3 in vecA with 22 33.
The Second Question
In this case, the same logic applies for subsetting, but running vecA[vecA %in% vecD$orig] gives you
[1] 5
as 7 does not exist in vecA. You are trying to replace a vector of length 1 with a vector of length 2, which is what triggers the warning. In this case, it will just replace the first element of vecD$repl which happens to be 55.
I have a list, "my_list", below:
$`2015-03-01 00:18:50`
integer(0)
$`2015-03-01 11:19:59`
[1] 4 6
$`2015-03-01 12:18:29`
[1] 12 13
$`2015-03-01 13:19:09`
[1] 1
$`2015-03-01 17:18:44`
integer(0)
$`2015-03-01 22:18:49`
integer(0)
I want to get the element index (not the subelement index) of the values greater than 0 (or where a list subelement is NOT empty). The output expected is a list that looks like:
2,2,3,3,4
I have gotten close with:
indices<-which(lapply(my_list,length)>0)
This piece of code however, only gives me the following and doesn't account for there being more than one subelement within a list element:
2,3,4
Does anyone know how to achieve what I am looking for?
We can use lapply along with a seq_along trick to bring in the indices of each element of the list. Then, for each list element, generate a vector of matching indices. Finally, unlist the entire list to obtain a single vector of matches.
x <- list(a=integer(0),b=c(4,6),c=c(12,13),d=c(1),e=integer(0),f=integer(0))
result <- lapply(seq_along(x), function(i) { rep(i, sum(x[[i]] > 0)) })
unlist(result)
[1] 2 2 3 3 4
Demo
You can try this, I hope this is what you have expected, Using lengths to calculate length of items in the list, then iterating every items of that list in rep command to get the final outcome:
lyst <- list(l1=integer(0), l2= c(1,2), l3=c(3,4), l4=character(0), l5=c(5,6,6))
lyst1 <- lengths(lyst)
unlist(lapply(1:length(lyst1), function(x)rep(x, lyst1[[x]])))
Output:
#> unlist(lapply(1:length(lyst1), function(x)rep(x, lyst1[[x]])))
#[1] 2 2 3 3 5 5 5
Repeat each numeric index by the respective length:
rep(seq_along(x), lengths(x))
#[1] 2 2 3 3 4
Using #Tim's x data.
I'm creating a function for intersecting a list of vectors.
The idea is for the function to reccur until it intersects the last two vectors in the the list and then move upward.
The problem is that this results in list(), even though there should definitely be an answer.
intersect_list <- function (x) {
if (length (x) == 1) {return (unique (x))}
else {intersect (x [[1]], intersect_list (x [-1]))
}
}
> listing
[[1]]
[1] 1 2 3 4
[[2]]
[1] -5 -4 -3 -2 -1 0 1 2 3 4 5 6
[[3]]
[1] 2 4
> intersect_list(listing)
list()
If I do everything manually, it works fine (naturally) and the output shuld be [1] 2 4.
Change the case when length(x)==1 to return a vector instead of a list.
intersect_list <- function (x) {
if (length (x) == 1) {return (unique (x[[1]]))}
else {intersect (x [[1]], intersect_list (x [-1]))
}
}
When unique is used on a lists it returns a list with all the unique elements. It doesn't recursively apply unique on each element. Since in the case when the input length is 1 we still have a list whose first element is a vector it ends up that unique will just return the input.
> unique(list(c(1,1,1,2)))
[[1]]
[1] 1 1 1 2
To see how unique is acting take a look at this example
> mylist <- list(1:2, 1:2, 3:4, c(1,1,1,2))
> unique(mylist)
[[1]]
[1] 1 2
[[2]]
[1] 3 4
[[3]]
[1] 1 1 1 2
The first two elements of mylist are the same vector so unique only returns a single instance of it.
So the issue with your function is that you were passing a list into unique which ends up returning a list. When intersect comes across a vector and a list it doesn't do what you were expecting it to.
> intersect(1:3, list(1:3))
list()
> intersect(1:3, list(1))
[[1]]
[1] 1
> intersect(list(1:3), list(1:3))
[[1]]
[1] 1 2 3
> intersect(list(1:3, 2:3), list(1:3))
[[1]]
[1] 1 2 3
By changing the unique(x) to unique(x[[1]]) we pass in the vector instead of the list which in turn takes the unique elements from that vector and returns a vector. Then both of the inputs to intersect will be a vector like you expected instead of having a list in there.
I used order() function to do the following
x<-c(12,5,13,8)
order(x)
It gives the following result, indicating it is in descending order
[1] 2 4 1 3
However, when I typed the following
x<-c(12,11,13,14)
order(x)
It gives a result that is in ascending order
[1] 2 1 3 4
I am not quite sure if I missed anything. Thanks for your help!
Order returns the row numbers in ascending order of x ( by default). So your output is as expected.
In case you were expecting the vector x to be ordered :
> x<-c(12,5,13,8)
# returns row numbers
> order(x)
[1] 2 4 1 3
# returns the ordered vector#############
> x[order(x)]
[1] 5 8 12 13
To order in descending order , use :
> x[order(x, decreasing = TRUE)]
[1] 13 12 8 5
You were just mistaken in the way you were reading the function.
The numbers that are being returned are the position in your vector.
Your first example:
x <- c(12,5,13,8)
order(x)
[1] 2 4 1 3
This is telling you that, in an ascending order, the first number is in the second position = 5, the second number is in the fourth position = 8, and so on.