Visualizando combinaciones de 2 letras

10

Las respuestas a esta pregunta en SO devolvieron un conjunto de aproximadamente 125 nombres de una a dos letras: /programming/6979630/what-1-2-letter-object-names-conflict-with-existing -r-objetos

  [1] "Ad" "am" "ar" "as" "bc" "bd" "bp" "br" "BR" "bs" "by" "c"  "C" 
 [14] "cc" "cd" "ch" "ci" "CJ" "ck" "Cl" "cm" "cn" "cq" "cs" "Cs" "cv"
 [27] "d"  "D"  "dc" "dd" "de" "df" "dg" "dn" "do" "ds" "dt" "e"  "E" 
 [40] "el" "ES" "F"  "FF" "fn" "gc" "gl" "go" "H"  "Hi" "hm" "I"  "ic"
 [53] "id" "ID" "if" "IJ" "Im" "In" "ip" "is" "J"  "lh" "ll" "lm" "lo"
 [66] "Lo" "ls" "lu" "m"  "MH" "mn" "ms" "N"  "nc" "nd" "nn" "ns" "on"
 [79] "Op" "P"  "pa" "pf" "pi" "Pi" "pm" "pp" "ps" "pt" "q"  "qf" "qq"
 [92] "qr" "qt" "r"  "Re" "rf" "rk" "rl" "rm" "rt" "s"  "sc" "sd" "SJ"
[105] "sn" "sp" "ss" "t"  "T"  "te" "tr" "ts" "tt" "tz" "ug" "UG" "UN"
[118] "V"  "VA" "Vd" "vi" "Vo" "w"  "W"  "y"

Y código de importación R:

nms <- c("Ad","am","ar","as","bc","bd","bp","br","BR","bs","by","c","C","cc","cd","ch","ci","CJ","ck","Cl","cm","cn","cq","cs","Cs","cv","d","D","dc","dd","de","df","dg","dn","do","ds","dt","e","E","el","ES","F","FF","fn","gc","gl","go","H","Hi","hm","I","ic","id","ID","if","IJ","Im","In","ip","is","J","lh","ll","lm","lo","Lo","ls","lu","m","MH","mn","ms","N","nc","nd","nn","ns","on","Op","P","pa","pf","pi","Pi","pm","pp","ps","pt","q","qf","qq","qr","qt","r","Re","rf","rk","rl","rm","rt","s","sc","sd","SJ","sn","sp","ss","t","T","te","tr","ts","tt","tz","ug","UG","UN","V","VA","Vd","vi","Vo","w","W","y")

Dado que el punto de la pregunta era crear una lista memorable de nombres de objetos para evitar, y la mayoría de los humanos no son tan buenos para dar sentido a un bloque sólido de texto, me gustaría visualizar esto.

Lamentablemente, no estoy exactamente seguro de la mejor manera de hacer esto. Había pensado en algo así como un diagrama de tallo y hojas, solo porque no hay valores repetidos, cada "hoja" se colocó en la columna correspondiente en lugar de dejarse justificada. O una adaptación de estilo wordcloud donde las letras se dimensionan de acuerdo con su prevalencia.

¿Cómo se puede visualizar de manera más clara y eficiente?

Las visualizaciones que se ajustan a lo siguiente en el espíritu de esta pregunta:

  • Objetivo principal: mejorar la capacidad de memorización del conjunto de nombres al revelar patrones en los datos

  • Objetivo alternativo: resaltar características interesantes del conjunto de nombres (por ejemplo, que ayudan a visualizar la distribución, las letras más comunes, etc.)

Se prefieren las respuestas en R, pero todas las ideas interesantes son bienvenidas.

Se permite ignorar los nombres de una sola letra, ya que son más fáciles de dar como una lista separada.

Ari B. Friedman
fuente

Respuestas:

12

Aquí hay un comienzo: visualícelos en una cuadrícula de primera y segunda letra:

combi <- c("Ad", "am", "ar", "as", "bc", "bd", "bp", "br", "BR", "bs", 
"by", "c",  "C",  "cc", "cd", "ch", "ci", "CJ", "ck", "Cl", "cm", "cn", 
"cq", "cs", "Cs", "cv", "d",  "D",  "dc", "dd", "de", "df", "dg", "dn", 
"do", "ds", "dt", "e",  "E",  "el", "ES", "F",  "FF", "fn", "gc", "gl", 
"go", "H",  "Hi", "hm", "I",  "ic", "id", "ID", "if", "IJ", "Im", "In", 
"ip", "is", "J",  "lh", "ll", "lm", "lo", "Lo", "ls", "lu", "m",  "MH", 
"mn", "ms", "N",  "nc", "nd", "nn", "ns", "on", "Op", "P",  "pa", "pf", 
"pi", "Pi", "pm", "pp", "ps", "pt", "q",  "qf", "qq", "qr", "qt", "r",  
"Re", "rf", "rk", "rl", "rm", "rt", "s",  "sc", "sd", "SJ", "sn", "sp", 
"ss", "t",  "T",  "te", "tr", "ts", "tt", "tz", "ug", "UG", "UN", "V",  
"VA", "Vd", "vi", "Vo", "w",  "W",  "y")

df <- data.frame (first = factor (gsub ("^(.).", "\\1", combi), 
                                  levels = c (LETTERS, letters)),
                  second = factor (gsub ("^.", "", combi), 
                                  levels = c (LETTERS, letters)),
                  combi = combi))

library(ggplot2)
ggplot (data = df, aes (x = first, y = second)) + 
   geom_text (aes (label = combi), size = 3) + 
   ## geom_point () +
   geom_vline (x = 26.5, col = "grey") + 
   geom_hline (y = 26.5, col = "grey")

(fue: dos letras) rejilla con letras

ggplot (data = df, aes (x = second)) + geom_histogram ()

segunda letra

ggplot (data = df, aes (x = first)) + geom_histogram ()

primera letra

Yo recojo:

  • de los nombres de una letra,

    • Afortunadamente i, j, k, y lestán disponibles (por lo que puede indexar hasta arrays 4D)
    • desafortunadamente t(tiempo), c(concentración) se han ido. Así son m(masa), V(volumen) y F(fuerza). Sin radio rni diámetro d.
    • Sin embargo, puedo tener presión ( p), cantidad de sustancia ( n) y longitud l.
    • Tal vez tenga que cambiar a nombres griegos: εestá bien, pero no debería

      π <- pi

      ?

  • Puedo tener el lowerUPPERnombre que quiera.

  • En general, comenzar con una letra mayúscula es una apuesta más segura que una minúscula.

  • no empieces con cod

cbeleites
fuente
Buen comienzo ¿Quizás agregar líneas de cuadrante (en un gran +) a través de la gráfica 2d para tener una mejor idea de dónde van las letras mayúsculas / minúsculas?
Ari B. Friedman
Pensé que hice eso. De todos modos, aquí está. @ gsk3: ¡gracias por subir las fotos!
Cbeleites descontento con SX
Agradable. Y por el contrario, gracias por proporcionar una respuesta interesante a la pregunta # 2. :-)
Ari B. Friedman
Mirando su diagrama 2D, otra sugerencia podría ser reducirlo a una cuadrícula de 27x26 y cambiar símbolos o colores (o fluctuación de fase con alfa) si una letra dada tiene menor / superior / ambos. También podría hacer que la fila de NA tenga un color diferente para separarla visualmente.
Ari B. Friedman
1
Eché un vistazo a 27 x 26 antes de publicar la respuesta (con el color y la forma según la primera y segunda letra en mayúscula). Pero eso no transmitía un mensaje fácil, por lo que inmediatamente volví a la grilla más grande.
Cbeleites descontento con SX
8

Ok, aquí está mi opinión muy rápida sobre una visualización tipo "tabla periódica", basada en la pregunta SO y los comentarios de los demás. El principal problema es la gran diferencia en el número de variables entre paquetes, lo que dificulta la visualización ... Me doy cuenta de que esto es muy difícil, así que no dude en cambiarlo como lo desee.

Aquí está la salida actual (de mi lista de paquetes) Parcela de ejemplo

Y el código

# Load all the installed packages
lapply(rownames(installed.packages()), require, 
       character.only = TRUE)
# Find variables of length 1 or 2
one_or_two <- unique(apropos("^[a-zA-Z]{1,2}$"))
# Find which package they come from
packages <- lapply(one_or_two, find)
# Some of the variables may belong to multiple packages, so determine the length 
# of each entry in packages and duplicate the names accordingly
lengths <- unlist(lapply(packages, length))
var.data <- data.frame(var = rep(one_or_two, lengths), 
                   package = unlist(packages))

Ahora, tenemos un marco de datos como este:

> head(var.data, 10)
   var           package
1   ar     package:stats
2   as   package:methods
3   BD    package:fields
4   bs      package:VGAM
5   bs   package:splines
6   by      package:base
7    c      package:base
8    C     package:stats
9   cm package:grDevices
10   D     package:stats

Ahora podemos dividir los datos por paquete

 data.split <- split(var.data, var.data$package)

Podemos ver que la mayoría de las variables provienen de la base y el paquete de estadísticas

> unlist(lapply(data.split, nrow))
     package:base  package:datasets    package:fields 
               16                 1                 2 
  package:ggplot2 package:grDevices  package:gWidgets 
                2                 1                 1 
  package:lattice      package:MASS    package:Matrix 
                1                 1                 3 
  package:methods      package:mgcv      package:plyr 
                3                 2                 1 
     package:spam   package:splines     package:stats 
                1                 2                14 
 package:survival     package:utils      package:VGAM 
                1                 2                 4 

Finalmente, la rutina de dibujo.

plot(0, 0, "n", xlim=c(0, 100), ylim=c(0, 120), 
     xaxt="n", yaxt="n", xlab="", ylab="")

side.len.x <- 100 / length(data.split)
side.len.y <- 100 / max(unlist(lapply(data.split, nrow)))
colors <- rainbow(length(data.split), start=0.2, end=0.6)    

for (xcnt in 1:length(data.split))
    {
    posx <- side.len.x * (xcnt-1)

    # Remove "package :" in front of the package name
    pkg <- unlist(strsplit(as.character(data.split[[xcnt]]$package[1]), ":"))
    pkg <- pkg[2]

    # Write the package name
    text(posx + side.len.x/2, 102, pkg, srt=90, cex=0.95, adj=c(0, 0))

    for (ycnt in 1:nrow(data.split[[xcnt]]))
        {
        posy <- side.len.y * (ycnt-1)
        rect(posx, posy, posx+side.len.x*0.85, posy+side.len.y*0.9, col = colors[xcnt])
        text(posx+side.len.x/2, posy+side.len.y/2, data.split[[xcnt]]$var[ycnt], cex=0.7)
        }
    }
nico
fuente
1
¡Agradable! Una forma interesante de tomar esto sería agruparlos por categoría (por ejemplo, paquetes de gráficos, prácticas de manipulación de datos, etc.), codificarlos por colores y luego hacer que la forma general sea más parecida a un cuadro que a un histograma.
Ari B. Friedman
+1 ¡Qué delicia! :) Muy buen trabajo. Supongo que lo único que sería necesario para obtener la funcionalidad de la tabla periódica es el diseño de la tabla. El PT estándar tiene 2 cuadrículas, con algunos elementos que faltan en el 1 superior, y los grupos se dividen / reorganizan (en oposición a 1 grupo = 1 columna vertical). Para ser honesto, esa no es la parte que pensé que sería difícil. El diseño de colores y bloques es la parte que más me emociona y es genial ver el código ggplot2 para ello.
Iterator
Necesito café. Veo que gsk3 tenía el mismo comentario con menos palabras. :) Creo que estaba fascinado por el color.
Iterator
1
@Iterator: tenga en cuenta que se trata de todas las funciones de trama estándar R, no hay ggplot2 involucrado :)
nico
Caballa Santa. ¡Tienes razón! Aún más impresionante. Mi conclusión: neeeeeeed coffeeeeeeeeeee.
Iterator
4

Aquí hay un histograma basado en letras. Consideró dimensionar las primeras letras por número, pero decidió no hacerlo, ya que eso ya está codificado en el componente vertical.

# "Load" data
nms <- c("Ad","am","ar","as","bc","bd","bp","br","BR","bs","by","c","C","cc","cd","ch","ci","CJ","ck","Cl","cm","cn","cq","cs","Cs","cv","d","D","dc","dd","de","df","dg","dn","do","ds","dt","e","E","el","ES","F","FF","fn","gc","gl","go","H","Hi","hm","I","ic","id","ID","if","IJ","Im","In","ip","is","J","lh","ll","lm","lo","Lo","ls","lu","m","MH","mn","ms","N","nc","nd","nn","ns","on","Op","P","pa","pf","pi","Pi","pm","pp","ps","pt","q","qf","qq","qr","qt","r","Re","rf","rk","rl","rm","rt","s","sc","sd","SJ","sn","sp","ss","t","T","te","tr","ts","tt","tz","ug","UG","UN","V","VA","Vd","vi","Vo","w","W","y") #all names
two_in_base <- c("ar", "as", "by", "cm", "de", "df", "dt", "el", "gc", "gl", "if", "Im", "is", "lh", "lm", "ls", "pf", "pi", "pt", "qf", "qr", "qt", "Re", "rf", "rm", "rt", "sd", "ts", "vi") # 2-letter names in base R
vowels <- c("a","e","i","o","u")
vowels <- c( vowels, toupper(vowels) )

# Constants
yoffset.singles <- 3

# Define a function to give us consistent X coordinates
returnX <- function(vec) {
  sapply(vec, function(x) seq(length(all.letters))[ x == all.letters ] )
}

# Make df of 2-letter names
combi <- nms[ sapply( nms, function(x) nchar(x)==2 ) ]
combidf <- data.frame( first = substr(combi,1,1), second=substr(combi,2,2) )
library(plyr)
combidf <- arrange(combidf,first,second)

# Add vowels
combidf$first.vwl <- (combidf$first %in% vowels)
combidf$second.vwl <- (combidf$second %in% vowels)

# Flag items only in base R
combidf$in_base <- paste(combidf$first,combidf$second,sep="") %in% two_in_base

# Create a data.frame to hold our plotting information for the first letters
combilist <- dlply(combidf,.(first),function(x) x$second)
combi.first <- data.frame( first = names(combilist), n = sapply(combilist,length) ,stringsAsFactors=FALSE )
combi.first$y <- 0
all.letters <-  c(letters,LETTERS) # arrange(combi.first,desc(n))$first to go in order of prevalence (which may break the one-letter name display)
combi.first$x <- returnX( combi.first$first )

# Create a data.frame to hold plotting information for the second letters
combidf$x <- returnX( combidf$first )
combidf$y <- unlist( by( combidf$second, combidf$first, seq_along ) )

# Make df of 1-letter names
sngldf <- data.frame( sngl = nms[ sapply( nms, function(x) nchar(x)==1 ) ] )
singles.y <- max(combidf$y) + yoffset.singles
sngldf$y <- singles.y
sngldf$x <- returnX( sngldf$sngl )

# Plot
library(ggplot2)
ggplot(data=combidf, aes(x=x,y=y) ) +
  geom_text(aes( label=second, size=3, colour=combidf$in_base ), position=position_jitter(w=0,h=.25)) +
  geom_text( data=combi.first, aes( label=first, x=x, y=y, size=4 ) ) +
  geom_text( data=sngldf, aes( label=sngl, x=x, y=y, size=4 ) ) +
  scale_size(name="Order (2-letter names)",limits=c(1,4),breaks=c(1,2),labels=c("Second","First")) +
  scale_x_continuous("",breaks=c(13,39),labels=c("lower","UPPER")) +
  scale_y_continuous("",breaks=c(0,5,singles.y),labels=c("First letter of two-letter names","Second letter of two-letter names","One-letter names") ) +
  coord_equal(1.5) +
  labs( colour="In base R" )

versión con nombres de una y dos letras en la misma trama

histograma basado en letras

Ari B. Friedman
fuente
2

Tabla periódica para 100, Alex. Sin embargo, no tengo código para ello. :(

Uno podría pensar que un paquete de "tabla periódica" ya podría existir en CRAN. La idea de un esquema de coloración y diseño de dichos datos podría ser interesante y útil.

Estos pueden ser coloreados por paquete y ordenados verticalmente por frecuencia, por ejemplo, en una muestra de código en CRAN o como aparecen en la base de código local.

Iterador
fuente
No estoy seguro si te sigo ... ¿podrías hacer un bosquejo simple de lo que estás pensando? No veo cómo un diseño de tabla periódica ayudaría aquí ...
nico
@nico: Estoy pensando en algo como esto: en.wikipedia.org/wiki/Periodic_table Supongamos que reemplazamos "elementos nobel" con los comandos base R. Los halógenos pueden ser reemplazados por los propios paquetes, etc. Con dicho paquete de visualización, dejaría que el usuario especifique la naturaleza de las filas, columnas, grupos y colorantes. Debería ser algo bastante simple de implementar, aunque lo haría de manera muy cruda. La ubicación sería tal que los elementos del mismo grupo (es decir, el paquete) estén cerca uno del otro. La ubicación vertical podría determinarse por la frecuencia de uso.
Iterator
¡Bueno, ahora lo entiendo! Tal vez intentaré ver si puedo salir con algo, pero primero necesito encontrar algo de tiempo libre ... :(
nico
Todavía no lo veo, pero estoy emocionado de ver en qué se convierte esta idea :-)
Ari B. Friedman
1
eché un vistazo a stackexchange: Tal Galili preguntó sobre PSE hace un tiempo, así que no pregunté. Pero yo sólo empujó un primer bit de código para r-fragua: pse.R complacer estrellas poner alrededor de la caja - No sé cómo escapar de ellos para que se desvanecen ...
cbeleites descontentos con SX
1

Las primeras dos páginas del capítulo 2 de ITILA de MacKay tienen diagramas agradables que muestran las probabilidades condicionales de todos los pares de caracteres en el idioma inglés. Puede encontrarlo útil.

Me da vergüenza decir que no recuerdo qué programa se utilizó para producirlos.

jcb
fuente
1
Es genial, pero me parece que todos dependen de tener alguna información adicional (prevalencia) asociada con cada par de letras. Por lo tanto, está graficando 3 dimensiones, mientras que principalmente graficamos 2 ... Sin embargo, me encantaría tener la información de prevalencia para R. Pero esa es una operación de minería de datos para otro día.
Ari B. Friedman