I am quite new to R and tried to create an empty list (names Input_IMPLEMENTATION) using:
Input_IMPLEMENTATION<-vector(mode="list",length=7)
However, this resulted in the following error:
Error in names(x) <- paste("V", seq_along(x), sep = "") :
'names' attribute [1] must be the same length as the vector [0]
If I use a different name for the list, everything works fine. for example:
Input_IMPLEMENTATION_a<-vector(mode="list",length=7)
Therefore, I assumed the error occurs as Input_IMPLEMENTATION is allready assigned some value. So I tried rm(Input_IMPLEMENTATION) before executing the code, but this did not change anything.
Does anyone have a hint for me, why I get this error?
Imagine the case to preallocate a 2x2 matrix with NAs. Now I would like to rename the first column to "Test" with
name_matrix<-matrix(NA,2,2)
colnames(name_matrix)[1] <- "Test"
But now I am getting the error message:
Error in dimnames(x) <- dn : length of 'dimnames' [2] not equal to array extent
Whereas if I convert the matrix to a data.frame first I am not ending up with this error message.
name_data_frame<-as.data.frame(name_matrix)
colnames(name_data_frame)[1] <- "Test"
My question is does anybody have an idea how to find out more about this unexpected behavior and maybe as well how to fix it?
The problem is that after the first line
name_matrix<-matrix(NA,2,2)
the value of colnames(name_matrix) is NULL for which it does not make sense to access its first entry colnames(name_matrix)[1].
Instead you have to assign the entire variable a vector of length 2.
For instance you could do:
colnames(name_matrix)<- c("Test", NA)
I have a dataframe with 10 columns in it. I want to retrieve the columns 1:4.
However I am storing the value 1:4 in a variable. Let's call it a. When I try to use df[,c(a)] it just gives me the numbers back. However, if I give df[,c(1:4)] it gives me the columns. What is the difference? If I use the function identical on these two: identical(c(a),c(1:4)), it gives me TRUE. What is that I am doing wrong?
I was able to figure this out. It was giving me this error :
Error in [.data.table(tr, 1, a) :
j (the 2nd argument inside [...]) is a single symbol but column name 'a' is not found. Perhaps you intended DT[,..a] or DT[,a,with=FALSE]. This difference to data.frame is deliberate and explained in FAQ 1.1.
So I had to use with=FALSE. This solved it.
Thanks!
Many thanks in advance for any advices or hints.
I'm working with data frames. The simplified coding is as follows:
`
f<-funtion(name){
x<-tapply(name$a,list(name$b,name$c),sum)
1) y<-dataset[[deparse(substitute(name))]]
#where dataset is an already existed list object with names the same as the
#function argument. I would like to avoid inputting two arguments.
z<-vector("list",n) #where n is also defined already
2) for (i in 1:n){z[[i]]<-x[y[[i]],i]}
...
}
lapply(list_names,f)
`
The warning message is:
In is.na(x) : is.na() applied to non-(list or vector) of type 'NULL'
and the output is incorrect. I tried debugging and found the conflict may lie in line 1) and 2). However, when I try f(name) it is perfectly fine and the output is correct. I guess the problem is in lapply and I searched for a while but could not get to the point. Any ideas? Many thanks!
The structure of the data
Thanks Joran. Checking again I found the problem might not lie in what I had described. I produce the full code as follows and you can copy-paste to see the error.
n<-4
name1<-data.frame(a=rep(0.1,20),b=rep(1:10,each=2),c=rep(1:n,each=5),
d=rep(c("a1","a2","a3","a4","a5","a6","a7","a8","a9","a91"),each=2))
name2<-data.frame(a=rep(0.2,20),b=rep(1:10,each=2),c=rep(1:n,each=5),
d=rep(c("a1","a2","a3","a4","a5","a6","a7","a8","a9","a91"),each=2))
name3<-data.frame(a=rep(0.3,20),b=rep(1:10,each=2),c=rep(1:n,each=5),
d=rep(c("a1","a2","a3","a4","a5","a6","a7","a8","a9","a91"),each=2))
#d is the name for the observations. d corresponds to b.
dataset<-vector("list",3)
names(dataset)<-c("name1","name2","name3")
dataset[[1]]<-list(c(1,2),c(1,2,3,4),c(1,2,3,4,5,10),c(4,5,8))
dataset[[2]]<-list(c(1,2,3,5),c(1,2),c(1,2,10),c(2,3,4,5,8,10))
dataset[[3]]<-list(c(3,5,8,10),c(1,2,5,7),c(1,2,3,4,5),c(2,3,4,6,9))
f<-function(name){
x<-tapply(name$a,list(name$b,name$c),sum)
rownames(x)<-sort(unique(name$d)) #the row names for
y<-dataset[[deparse(substitute(name))]]
z<-vector("list",n)
for (i in 1:n){
z[[i]]<-x[y[[i]],i]}
nn<-length(unique(unlist(sapply(z,names)))) # the number of names appeared
names_<-sort(unique(unlist(sapply(z,names)))) # the names appeared add to the matrix
# below
m<-matrix(,nrow=nn,ncol=n);rownames(m)<-names_
index<-vector("list",n)
for (i in 1:n){
index[[i]]<-match(names(z[[i]]),names_)
m[index[[i]],i]<-z[[i]]
}
return(m)
}
list_names<-vector("list",3)
list_names[[1]]<-name1;list_names[[2]]<-name2;list_names[[3]]<-name3
names(list_names)<-c("name1","name2","name3")
lapply(list_names,f)
f(name1)
the lapply(list_names,f) would fail, but f(name1) will produce exactly the matrix I want. Thanks again.
Why it doesn't work
The issue is the calling stack doesn't look the same in both cases. In lapply, it looks like
[[1]]
lapply(list_names, f) # lapply(X = list_names, FUN = f)
[[2]]
FUN(X[[1L]], ...)
In the expression being evaluated, f is called FUN and its argument name is called X[[1L]].
When you call f directly, the stack is simply
[[1]]
f(name1) # f(name = name1)
Usually this doesn't matter, but with substitute it does because substitute cares about the name of the function argument, not its value. When you get to
y<-dataset[[deparse(substitute(name))]]
inside lapply it's looking for the element in dataset named X[[1L]], and there isn't one, so y is bound to NULL.
A way to get it to work
The simplest way to deal with this is probably to just have f operate on character strings and pass names(list_names) to lapply. This can be accomplished fairly easily by changing the beginning of f to
f<-function(name){
passed.name <- name
name <- list_names[[name]]
x<-tapply(name$a,list(name$b,name$c),sum)
rownames(x)<-sort(unique(name$d)) #the row names for
y<-dataset[[passed.name]]
# the rest of f...
and changing lapply(list_names, f) to lapply(names(list_names),f). This should give you what you want with nearly minimal modification, but you also might consider also renaming some of your variables so the word name isn't used for so many different things--the function names, the argument of f, and all the various variables containing name.