1

What I tried to do:

In aphid package there is a function deriveHMM() which needs to be fed with a list like:

x <- list(c("c"="10.0", "b"="5.0","c"="10.0", "a"="1.0", "a"="2.0",...))

which needs to be created of a very large input vector like

iv <- c(10, 5, 10, 1, 2,...)

It is important, that the order of my original input vector remains unchanged.

I need to automatically create this list by a large input of doubles from a .csv file (import of doubles to R worked fine). Each double has to get a name depending on its closest distance to a predefined value, for example:

  • all doubles ranging from 0 to 2.5 should be named "a"
  • all doubles ranging from 2.5 to 7.5 should be named "b"
  • all doubles greater than 7.5 should be named "c"

and after that all doubles be converted to a character (or string (?)) so the method deriveHMM() accepts the input.

I would be very happy to have suggestions. I am new to R and this is my first post on Stackoverflow.com. I am not an experienced programmer, but I try my best to understand your help.

EDIT:
Updated the question, because what I need is a "List of named vectors of characters", exactly like in my example above without changing the order.

Jason Aller
  • 3,541
  • 28
  • 38
  • 38
  • 1
    Check `cut` and its `breaks` and `labels` argument, as described e.g. here: [Convert continuous numeric values to discrete categories defined by intervals](https://stackoverflow.com/a/13559298/1851712). Then set names of the result (`setNames`) and convert to `list`. – Henrik Dec 17 '18 at 13:24
  • Unfortunately it didn´t solve my problem, because i need to maintain the order of the named vectors in the list – Helle Brezel Dec 18 '18 at 13:04
  • Sorry, I don't understand. The order does not change if you `cut` your vector: `setNames(iv, cut(iv, c(0, 2.5, 7.5, Inf), labels = letters[1:3]))`. – Henrik Dec 18 '18 at 13:15
  • I´m sorry, i got the comment section wrong, this all kinda new to me. Your solution doesn´t change the order, you are right. But it is still not accepted by the method because it puts out named doubles. – Helle Brezel Dec 18 '18 at 13:21
  • Just wrap in `as.character` then...`setNames(as.character(iv), cut(iv, c(0, 2.5, 7.5, Inf), labels = letters[1:3]))` – Henrik Dec 18 '18 at 13:24

2 Answers2

2

This solution uses findInterval to get an index into a tags vector, the vector of names.

set.seed(1234)    # Make the results reproducible
x <- runif(10, 0, 20)

tags <- letters[1:3]
breaks <- c(0, 2.5, 7.5, Inf)

names(x) <- tags[findInterval(x, breaks)]

x
#         a          c          c          c          c 
# 2.2740682 12.4459881 12.1854947 12.4675888 17.2183077 
#         c          a          b          c          c 
#12.8062121  0.1899151  4.6510101 13.3216752 10.2850228

Edit.

If you need x to be of class "character", get the index into tags first, then coerce x to character and only then assign the names attribute.

i <- findInterval(x, breaks)
x <- as.character(x)
names(x) <- tags[i]
x
#                  a                   c                   c 
# "2.27406822610646"  "12.4459880962968"  "12.1854946576059" 
#                  c                   c                   c 
# "12.4675888335332"  "17.2183076711372"  "12.8062121057883" 
#                  a                   b                   c 
#"0.189915127120912"  "4.65101012028754"   "13.321675164625" 
#                  c 
# "10.2850228268653" 
Rui Barradas
  • 70,273
  • 8
  • 34
  • 66
  • this would be the perfect solution, if the named doubles could be converted to named characters. Unfortunately deriveHMM() doesn´t work with named doubles. When I try to convert them via as.character() the name tags get lost again – Helle Brezel Dec 18 '18 at 13:13
1

Here is an example, where x represents your input vector.

x <- seq(1, 10, 0.5)

The first step is to give your elements names depending on their values.

names(x) <- ifelse(x <= 2.5, "a", ifelse(x > 2.5 & x <= 7.5, "b", "c"))

Next, split your vector and a apply as.character. We can use by here.

lst <- by(x, names(x), as.character, simplify = TRUE)
is.list(lst)
# [1] TRUE

Result

lst
#names(x): a
#[1] "1"   "1.5" "2"   "2.5"
#----------------------------------------------------------------------------------------------------------------------- 
#names(x): b
# [1] "3"   "3.5" "4"   "4.5" "5"   "5.5" "6"   "6.5" "7"   "7.5"
#----------------------------------------------------------------------------------------------------------------------- 
#names(x): c
#[1] "8"   "8.5" "9"   "9.5" "10" 

You could also use split and lapply as shown below, by is shorthand of such an approach.

lapply(split(x, names(x)), as.character)
markus
  • 25,843
  • 5
  • 39
  • 58
  • See the last code line of [this](https://stackoverflow.com/questions/46251725/convert-named-vector-to-list-in-r/46251794#46251794) – Rui Barradas Dec 17 '18 at 13:28