Cómo crear una columna que contiene una serie de estrellas para indicar los niveles de un factor en una trama de datos en R
Pregunta
(segunda pregunta hoy - debe ser un mal día)
Tengo una trama de datos con varias columnas, inculding una columna de concentración (numérico), una bandera destacando resultados no válidos (booleano) y una descripción del problema (carácter)
df <- structure(list(x = c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10), rawconc = c(77.4,
52.6, 86.5, 44.5, 167, 16.2, 59.3, 123, 1.95, 181), reason = structure(c(NA,
NA, 2L, NA, NA, NA, 2L, 1L, NA, NA), .Label = c("Fails Acceptance Criteria",
"Poor Injection"), class = "factor"), flag = c("False", "False",
"True", "False", "False", "False", "True", "True", "False", "False"
)), .Names = c("x", "rawconc", "reason", "flag"), row.names = c(NA,
-10L), class = "data.frame")
Me puede crear una columna con el nivel numérico de la columna de la razón
df$level<-as.numeric(df$reason)
df
x rawconc reason flag level
1 1 77.40 <NA> False NA
2 2 52.60 <NA> False NA
3 3 86.50 Poor Injection True 2
4 4 44.50 <NA> False NA
5 5 167.00 <NA> False NA
6 6 16.20 <NA> False NA
7 7 59.30 Poor Injection True 2
8 8 123.00 Fails Acceptance Criteria True 1
9 9 1.95 <NA> False NA
10 10 181.00 <NA> False NA
y esto es lo que quiero hacer para crear una columna con muchas estrellas 'nivel', pero falla
df$stars<-paste(rep("*",df$level)sep="",collapse="")
Error: unexpected symbol in "df$stars<-paste(rep("*",df$level)sep"
df$stars<-paste(rep("*",df$level),sep="",collapse="")
Error in rep("*", df$level) : invalid 'times' argument
rep("*",df$level)
Error in rep("*", df$level) : invalid 'times' argument
df$stars<-paste(rep("*",pmax(df$level,0,na.rm=TRUE)),sep="",collapse="")
Error in rep("*", pmax(df$level, 0, na.rm = TRUE)) :
invalid 'times' argument
Parece que las necesidades rep a ser alimentados con un valor a la vez. Siento que esto debería ser posible (y mi tripa dice el 'uso lapply' pero mi Fu es aplicable v. Pobres)
Cualquier uno quiere probar?
Solución
creo que se necesita una función del tipo de aplicación. Esto funcionará:
df[is.na(df$level),"level"] <- 0
df$level <- sapply(df$level, function(x) paste(rep("*",x),collapse=""))
sería mejor usar sapply
que lapply
en este caso ya que devuelve un vector en lugar de una lista.
A partir de la ayuda para el representante:
Si 'tiempos' se compone de una sola entero, el resultado consta de toda la entrada de repetir esto muchas veces. Si los tiempos '' es un vector de la misma longitud que 'x' (después de la replicación por 'cada'), el resultado consta de 'x [1]' 'repetidas veces [1]' veces, 'x [2]' repetidas veces '[2]' veces y así sucesivamente.
Uno de los problemas con el uso de rep
con un vector para los tiempos parámetro es que sólo devuelve un vector y descarta casos cuando los tiempos = 0. Esto se puede ver con este comando:. rep(rep("*", nrow(df)), times=df$level)
Otros consejos
Se puede crear vectores estrellas como
vstars <- sapply(1L:nlevels(df$reason), function(i) paste(rep("*",i),collapse=""))
vstars
# [1] "*" "**"
Y a continuación, la indexación con df$reason
(que funciona porque su factor a):
vstars[df$reason]
# [1] NA NA "**" NA NA NA "**" "*" NA NA
Para grandes data.frame
debería ser mucho más rápido que paste
en cada fila.