varias superponer graficos graficas ggplot r character

superponer - Crea una secuencia entre dos letras.



superponer graficas en r (8)

Quiero crear una secuencia entre dos letras, digamos "b" y "f" . Así que la salida es

"b" "c" "d" "e" "f"

Para números podemos hacer

2:6 #which gives output as [1] 2 3 4 5 6

¿Hay una manera fácil de hacer esto con letras también?

He pasado por Generar una secuencia de caracteres de ''A'' - ''Z'', pero esto produce todas las letras y no una secuencia entre letras específicas.

Mi solución actual es,

indx <- which(letters %in% c("b", "f")); letters[indx[1] : indx[2]] #[1] "b" "c" "d" "e" "f"

Esto funciona, pero tengo curiosidad por saber si hay una manera fácil de hacer esto o una función en alguno de los paquetes que me he perdido.

Nota: No quiero letters[2:6] ya que no sé 2 y 6 de antemano. Podría estar entre dos letras cualquiera.


Esta sería otra opción de base R:

letters[(letters >= "b") & (letters <= "f")] # [1] "b" "c" "d" "e" "f"


Jugando con UTF, algo como:

intToUtf8(utf8ToInt("b"):utf8ToInt("f"), multiple = TRUE) # [1] "b" "c" "d" "e" "f"


Lo primero es lo primero: tu código

which(letters %in% c("b", "f"))

Es una forma de escribir válida pero complicada.

match(c(''b'', ''f''), letters)

(¿Por qué "enrevesado"? Porque %in% es una envoltura alrededor de una match para un caso de uso específico, que convierte explícitamente el índice numérico en un valor lógico, es decir, la operación inversa de la which ).

Luego, por supuesto, puede usar el resultado y convertirlo en un rango a través de idx[1L] : idx[2L] y no hay nada de malo en esto en este caso. Pero R tiene una forma idiomática de expresar el concepto de llamar a una función utilizando un vector como sus parámetros: do.call :

do.call(`:`, as.list(match(c(''b'', ''f''), letters)))

O equivalente:

do.call(seq, as.list(match(c(''b'', ''f''), letters)))

{purrr} nos permite hacer lo mismo sin la lista as.list :

purrr::invoke(seq, match(c(''b'', ''f''), letters))

Y, finalmente, subconjunto:

letters[purrr::invoke(seq, match(c(''b'', ''f''), letters))]


Otra opción con match , seq y do.call :

letters[do.call(seq, as.list(match(c("b","f"), letters)))]

lo que da:

[1] "b" "c" "d" "e" "f"

Haciendo una función de esto de tal manera que funcione con mayúsculas y minúsculas:

char_seq <- function(lets) { switch(all(grepl("[[:upper:]]", lets)) + 1L, letters[do.call(seq, as.list(match(lets, letters)))], LETTERS[do.call(seq, as.list(match(lets, LETTERS)))]) }

la salida de este:

> char_seq(c("b","f")) [1] "b" "c" "d" "e" "f" > char_seq(c("B","F")) [1] "B" "C" "D" "E" "F"

Esta función se puede ampliar con verificaciones de la exactitud de la entrada:

char_seq <- function(lets) { g <- grepl("[[:upper:]]", lets) if(length(g) != 2) stop("Input is not of length 2") if(sum(g) == 1) stop("Input does not have all lower-case or all upper-case letters") switch(all(g) + 1L, letters[do.call(seq, as.list(match(lets, letters)))], LETTERS[do.call(seq, as.list(match(lets, LETTERS)))]) }

dando como resultado mensajes de error adecuados cuando la entrada no es correcta:

> char_seq(c("B")) Error in char_seq(c("B")) : Input is not of length 2 > char_seq(c("b","F")) Error in char_seq(c("b", "F")) : Input does not have all lower-case or all upper-case letters


Por qué no?

letters[which(letters == ''b'') : which(letters == ''f'')]


Puedes crear tu propia función:

`%:%` <- function(l, r) { intToUtf8(seq(utf8ToInt(l), utf8ToInt(r)), multiple = TRUE) }

Uso:

"b" %:% "f" # [1] "b" "c" "d" "e" "f" "f" %:% "b" # [1] "f" "e" "d" "c" "b" "A" %:% "D" # [1] "A" "B" "C" "D"


Sé que está mal visto, pero aquí hay una solución eval(parse(...))

LETTERS[eval(parse(text = paste(which(LETTERS %in% c(''B'', ''F'')), collapse = '':'')))] #[1] "B" "C" "D" "E" "F"


Tal vez el uso de las versiones en bruto de las letras y luego la conversión de nuevo al carácter podría usarse para definir una función de infijo análoga a ":"

`%c:%` <- function(x,y) { strsplit( rawToChar(as.raw( seq(as.numeric(charToRaw(x)), as.numeric(charToRaw(y))))), "" )[[1]]} > ''a'' %c:% ''g'' [1] "a" "b" "c" "d" "e" "f" "g"

Ciertamente no estoy afirmando que esto satisfaga la solicitud de "una forma fácil de hacer esto" y ni siquiera estoy seguro de que sea más eficiente, pero presenta un par de funciones potencialmente útiles.