1

Is it possible to store a numeric vector in the names variable of a list? ie.

x <- c(1.2,3.4,5.9)
alist <- list()
alist[[x]]$somevar <- 2

I know I can store it as a vector within the list element, but I thought it would be faster to move through and find the element of the list I want (or add if needed) if the numeric vector is the name of the list element itself...

EDIT: I have included a snippit of the code in context below, apologies for the change in nomenclature. In brief, I am working on a clustering problem, the dataset is too large to directly do the distance calculation on, my solution was to create bins for each dimension of the data and find the nearest bin for each observation in the original data. Of course, I cannot make a complete permutation matrix since this would be larger than the original data itself. Therefore, I have opted to find the nearest bin for each dimension individually and add it to a vector, temp.bin, which ideally would become the name of the list element in which the rowname of the original observation would be stored. I was hoping that this would simplify searching for and adding bins to the list.

I also realise that the distance calculation part is likely wrong - this is still very much a prototype.

binlist <- list()
for(i in 1:nrow(data)) # iterate through all data points
{
# for each datapoint make a container for the nearest bin found
temp.bin <- vector(length = length(markers))
names(temp.bin) <- markers
for(j in markers) # and dimensions 
{
  # find the nearest bin for marker j
  if(dist == "eucl")
  {
    dists <- apply(X=bin.mat, MARGIN = 1, FUN= function(x,y) {sqrt(sum((x-y)^2))}, y=data[i,j])
    temp.bin[j] <- bin.mat[which(dists == min(dists)),j]
  }
}
### I realise this part doesn't work
binlist[[temp.bin]] <- append(binlist[[temp.bin]], values = i)

The closest answer so far is John Coleman.

JulianS
  • 188
  • 7
  • Do I get something wrong, or is x meant to store indices at which you want to do something within the list? – loki Feb 15 '18 at 10:42
  • 1
    After a first read, it isn't entirely clear what you wanted, as you can see we already have three different solutions. Please clarify the question. – catastrophic-failure Feb 15 '18 at 12:40

2 Answers2

2

names(alist) is a character vector. A numeric vector is not a string, hence it isn't a valid name for a list element. What you want is thus impossible. You could create a string representation of such a list and use that as a name, but that would be cumbersome. If this is what you really wanted to do, you could do something like the following:

x <- c(1.2,3.4,5.9)
alist <- list()
alist[[paste(x,collapse = " ")]]$somevar <- 2

This will create a 1-element list whose only element has the name "1.2 3.4 5.9".

While there might be some use cases for this, I suspect that you have an XY problem. What are you trying to achieve?

John Coleman
  • 51,337
  • 7
  • 54
  • 119
  • While this solution would work. It would then require an additional step at the end of the script to return the character vector back into the numeric vector. Correct me if I am wrong, but wouldn't the character form make it slower to iterate through the list to find a matching name? – JulianS Feb 15 '18 at 17:16
  • 1
    @JulianS I did say that it is cumbersome. There is no direct way to use an actual numerical vector for a name since names need to be strings. Converting such a vector to a string is probably not the best idea, but my answer shows how it is possible to do so. As I hinted at the end, I suspect that this approach answers the question that you actually asked (the "X"), but doesn't answer the question that you possibly should have asked (the "Y", whatever than may be). – John Coleman Feb 15 '18 at 17:26
  • @JulianS A (list) name has to be a `character` in R. – catastrophic-failure Feb 15 '18 at 17:26
1

Solution

With some slight modifications we can achieve the following:

x = c(1.2,3.4,5.9)
alist = vector("list", length(x))
names(alist) = x
alist[as.character(x)] = list(c(somevar = 2))
#$`1.2`
#somevar 
#      2 
#
#$`3.4`
#somevar 
#      2 
#
#$`5.9`
#somevar 
#      2 

Explanation

Basically:

  • I had to create the list with the correct length (vector("list", length(x)))
  • Then assign the correct names (names(alist) = x)
  • So we can call list levels by name using [ and assign a new list to each list element (alist[as.character(x)] = list(c(somevar = 2)))

2nd Solution

Going by John Coleman comment:

It isn't clear that you answered the question. You gave a list whose vector of names is the the vector x, coerced to character. OP asked if it was possible "if the numeric vector is the name of the list element itself... ". They wanted to treat x as a single name, not a vector of names.

If you wanted to have the list element named after the vector x you could try, using the deparse(substitute(.)) trick

x = c(1.2,3.4,5.9)
alist = list()
alist[[deparse(substitute(x))]]$somevar = 2
#> alist[[deparse(substitute(x))]]
#$somevar
#[1] 2

If you really wanted the numeric values in x as the name itself, then I point you to John's solution.

catastrophic-failure
  • 3,759
  • 1
  • 24
  • 43
  • @loki it doesn't, R uses the integer part of `x`, see that `alist[x[2]]` returns the list named after `5.9`, the third element, as `x[2]` has been assigned the value `3.4`. – catastrophic-failure Feb 15 '18 at 10:50
  • Your user name is appropriate for this. Storing numeric data as names is a bad idea, – Roland Feb 15 '18 at 11:14
  • @Roland That would be a soft error ;) I only answered what the question asked for. – catastrophic-failure Feb 15 '18 at 12:15
  • 1
    It isn't clear that you answered the question. You gave a list whose vector of names is the the vector `x`, coerced to character. OP asked if it was possible "if the numeric vector is the name of the list *element* itself... ". They wanted to treat `x` as a single name, not a vector of names. – John Coleman Feb 15 '18 at 12:25
  • @JohnColeman Point taken, it also makes sense that way, OP should clarify. – catastrophic-failure Feb 15 '18 at 12:33
  • 1
    @catastrophic-failure I agree, it wasn't the clearest question. Your interpretation was reasonable. In fact, +1 since it might be what they had in mind. – John Coleman Feb 15 '18 at 12:33
  • Given this is a clustering problem I cannot know the length of the list _a priori_. The first solution just splits the original numeric vector into separate elements of the list, the point is to keep them together as an index to find within the list. So yes, to clarify it is imperative to treat `x` as a single entity and store it as such. To make it easier to iterate through the list, I thought it easier to use it as the name... – JulianS Feb 15 '18 at 17:20