I would like to delete nested items of a R list that contain the string available. However, I need to keep the list size (i.e. NULL if all items deleted). The below code generate a possible input from which all items should be removed:
nested.list <- list()
for(lop in 1:4){
nested.list[[lop]] <- c("available","available")}
The expected output is:
for(lop in 1:4){
nested.list.out[lop] <- list(NULL)}
However, if the item is other than available, it should be kept. Let's assume the following input:
nested.list[[1]][[2]] <- "hold"
The expected output would be:
nested.list.out[[1]] <- "hold"
It is important to highlight that the string hold is only to exemplify. In my real data-set, each item of each nested list can have random strings and should all be kept in my output. Any idea to do it wisely?
The simplest way is to use lapply to loop over the list. On each iteration remove all available strings and return NULL if a resulting vector is empty.
nested.list.out <- lapply(nested.list, function(x) {
x <- x[x != "available"] # Remove "available" from vector
if (length(x) < 1){
# Here resulting vector is empty, so return NULL
return(NULL)
} else {
return(x)
}
})
Related
I'm trying to save each iteration of this for loop in a vector.
for (i in 1:177) {
a <- geomean(er1$CW[1:i])
}
Basically, I have a list of 177 values and I'd like the script to find the cumulative geometric mean of the list going one by one. Right now it will only give me the final value, it won't save each loop iteration as a separate value in a list or vector.
The reason your code does not work is that the object ais overwritten in each iteration. The following code for instance does what precisely what you desire:
a <- c()
for(i in 1:177){
a[i] <- geomean(er1$CW[1:i])
}
Alternatively, this would work as well:
for(i in 1:177){
if(i != 1){
a <- rbind(a, geomean(er1$CW[1:i]))
}
if(i == 1){
a <- geomean(er1$CW[1:i])
}
}
I started down a similar path with rbind as #nate_edwinton did, but couldn't figure it out. I did however come up with something effective. Hmmmm, geo_mean. Cool. Coerce back to a list.
MyNums <- data.frame(x=(1:177))
a <- data.frame(x=integer())
for(i in 1:177){
a[i,1] <- geomean(MyNums$x[1:i])
}
a<-as.list(a)
you can try to define the variable that can save the result first
b <- c()
for (i in 1:177) {
a <- geomean(er1$CW[1:i])
b <- c(b,a)
}
I'm new to R. Reading Book Of R by Tilman Davies. An example is provided for how to use an externally defined helper function which incidentally utilizes double square brackets [[]]. Please explain what helper.call[[1]] and helper.call[[2]] are doing and use of double brackets here.
multiples_helper_ext <- function(x=foo,matrix.flags,mat=diag(2){
indexes <- which(matrix.flags)
counter <- 0
result <- list()
for(i in indexes){
temp <- x[[i]]
if(ncol(temp)==nrow(mat)){
counter <- counter+1
result[[counter]] <- temp%*%mat
}
}
return(list(result,counter))
}
multiples4 <- function(x,mat=diag(2),str1="no valid matrices",str2=str1){
matrix.flags <- sapply(x,FUN=is.matrix)
if(!any(matrix.flags)){
return(str1)
}
helper.call <- multiples_helper_ext(x,matrix.flags,mat=diag(2)
result <- helper.call[[1]] #I dont understand this use of double bracket
counter <- helper.call[[2]] #and here either
if(counter==0){
return(str2)
} else {
return(result)
}
}
foo <- list(matrix(1:4,2,2),"not a matrix","definitely not a matrix",matrix(1:8,2,4),matrix(1:8,4,2))
In R there are two basic types of objects: lists and vectors. The items of lists can be other objects, the items of of vectors are usually numbers, strings, etc.
To access items in a list, you use the double bracket [[]]. This gives back the object at that place of the list.
So
x <- 1:10
x is now a vector of integers
L <- list( x, x, "hello" )
L is a list whose first item is the vector x, its second item is the vector x, and its third item is the string "hello".
L[[2]]
This give back a vector, 1:10, which is stored in the 2nd place in L.
L[2]
This is a bit confusing, but this gives back a list whose only item is 1:10, i.e. it only contains L[[2]].
In R, when you want to return multiple values, you usually do this with a list. So, you might end you function with
f <- function() {
return( list( result1="hello", result2=1:10) )
}
x = f()
Now you can access the two results with
print( x[["result1"]] )
print( x[["result2"]] )
You can also access items of a list with ''$, so instead you can write
print( x$result1 )
print( x$result2 )
The syntax [[]] is used for list in python. Your helper.call is a list (of result and counter), so helper.cal[[1]] returns the first element of this list (result).
Have a look here: Understanding list indexing and bracket conventions in R
I've constructed an empty list but with names, something like this:
lvls = letters[1:5]
tree <- tree <- vector("list", length(lvls))
names(tree) <- lvls
Now I'd like to assign an obj, in this case another list, to each of the names in the list, but using variables in a loop. I have this:
for(l in lvls){
tree[[l]] <- vector("list", 5)
}
But it assigns to indices instead of by name. What I need is something like:
for(l in lvls){
tree$l <- vector("list", 5)}
But this won't work, b/c the l is taken as a literal instead of a variable. Anyone know how I could change that?
EDIT:
I don't have a thorough grasp of R data structures. But it looks like the assignment format I used does work, only that assigning a list to the extension names was problematic.
for(l in lvls){
tree[[l]] <- "test_string"
}
The above code does assign similar to tree$var_name, as far as I know.
It is not clear the output you need, when using this loop:
for (l in lvls){
tree[[l]] <- vector("list", 5)
}
produces the a list of five lists
$a
$a[[1]]
NULL
$a[[2]]
NULL
$a[[3]]
NULL
$a[[4]]
NULL
$a[[5]]
NULL
....
EDIT: I solved this one on my own. It had nothing to do with the function object assignment, it was that I was assigning the results to a vector "[]" rather then to a list "[[]]"
here's more reading on the subject: The difference between [] and [[]] notations for accessing the elements of a list or dataframe
I'm trying to filter event data. Depending on what I'm looking at I've got to do the filtering different ways. I've got two functions that I use for filtering (I use them throughout my project, in addition to this instance):
drop_columns <- function(x, ...) {
selectors <- list(...)
return(x[ , -which(names(x) %in% selectors)])
}
filter_by_val <- function(x, col, ...) {
return(x[ which(x[, col] %in% ...), ])
}
Here's the function that choses which function does the filtering, and then executes it. Note that I'm assigning the function to an object called "filter_method":
filter_playtime_data <- function (key_list, data) {
filter_method <- NULL
out_list <- list()
if(key_list$kind == "games") {
filter_method <- function(key_list) {
drop_columns(filter_by_val(data, "GameTitle", key_list), "X")
}
} else if (key_list$kind == "skills") {
filter_method <- function(key_list) {
filter_by_val(data, "Skill", key_list)
}
}
# Separate data with keys
out_list["ELA"] <- filter_method(key_list[["ELA"]])
out_list["MATH"] <- filter_method(key_list[["MATH"]])
out_list["SCI"] <- filter_method(key_list[["SCI"]])
return (out_list)
}
I'm trying to filter data based on "skills" (ie. using filter_by_val) and it's not working as expected. I'm feeding in a data.frame and I'm expecting a data.frame to come out, but instead I'm getting a list of indexes, as if the function is only returning this part of my function: -which(names(x) %in% selectors)
When I run this is the debug browser -- ie. filter_method(key_list[["ELA"]]) -- it works as expected, I get the data frame. But the values held in my output list: out_list[[ELA]] is the list of indexes. Any idea what's happening?
I am trying to compile two vectors from my for loop, to then cbind into a table. (I was trying to do this all in one step, but because of the below issue I'm trying to simplify.)
I set three vectors, id_name, count_rows, and id_test.
Going through my new_dat (a pre-exiting data frame), I'm setting vector result to be the number of the rows where the ID is i.
I'm then printing the output, which works fine.
But when I try to push the values into the vectors, I get Error: object 'id_name' not found. And the same for the other two.
Here's my code:
id_name <- c()
count_rows <- c()
id_test <- c()
for (i in id) {
result <- sum(new_dat$ID == i)
id_test <- c("hello", "world")
id_name <- c(id_name, i)
count_rows <-c(count_rows, result)
print(result)
print(i)
}
Initialize your vectors differently. See below; you may need to change numeric if your data aren't numeric, and substitute the data's actual length for N (if you know it beforehand).
id_name <- vector('numeric', length=N)
What you are doing now creates a NULL variable, of class NULL.