Come creare una colonna contenente una stringa di stelle per indicare i livelli di un fattore in un frame di dati in R
Domanda
(seconda domanda oggi - deve essere una brutta giornata)
Ho una dataframe con varie colonne, inculding una colonna concentrazione (numerico), un flag evidenziando risultati non validi (boolean) e una descrizione del problema (carattere)
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")
I può creare una colonna con il livello numerico della colonna ragione
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
ed ecco cosa voglio fare per creare una colonna con molte stelle 'Level', ma non riesce
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
Sembra che le esigenze rep da alimentare un valore alla volta. Credo che questo dovrebbe essere possibile (e il mio intestino dice 'uso lapply', ma il mio applicare Fu è v. Scarso)
Ogni uno vuole provare?
Soluzione
Credo che avrete bisogno di una funzione di applicazione di tipo. Ciò funzionerà:
df[is.na(df$level),"level"] <- 0
df$level <- sapply(df$level, function(x) paste(rep("*",x),collapse=""))
Si sarebbe meglio utilizzare sapply
di lapply
in questo caso in quanto restituisce un vettore al posto di una lista.
Dalla aiuto per rep:
Se 'tempi' costituito da un unico intero, il risultato è costituito da tutto ingresso ripetuto molte volte. Se 'volte' è un vettore della stessa lunghezza come 'x' (dopo la replica 'ogni'), la risultato consiste di 'x [1]' utilizzate 'volte [1]' volte, 'x [2]' ripetuti 'volte [2]' volte e così via.
Un problema con l'utilizzo di rep
con un vettore per i tempi parametro è che semplicemente restituisce un vettore e scarta casi in cui i tempi = 0. Si può vedere questo con questo comando:. rep(rep("*", nrow(df)), times=df$level)
Altri suggerimenti
Si potrebbe creare stelle vettore come
vstars <- sapply(1L:nlevels(df$reason), function(i) paste(rep("*",i),collapse=""))
vstars
# [1] "*" "**"
E poi l'indicizzazione con df$reason
(che funziona perché il suo fattore di a):
vstars[df$reason]
# [1] NA NA "**" NA NA NA "**" "*" NA NA
Per gran data.frame
dovrebbe essere molto più veloce poi paste
in ogni riga.