cerrar-sesion editar-perfil marker video calendario monitor periodico fax rss twitter facebook google-plus linkedin alarma circulo-derecha abajo derecha izquierda mover-vertical candado usuario email lupa exito mapa email2 telefono etiqueta

400440308. Nubes de Etiquetas: Usabilidad y matemáticas

Escrito por Redacción en Secciones
no hay comentarios Haz tu comentario
Imagen de logotipo de facebook Imagen de logotipo de Twitter Imagen de Logotipo de Google+ Imagen de logotipo de Linkedin

Según Wikipedia, Flickr.com fue el primer sitio web en utilizar nubes de etiquetas para la navegación. Ahora, no obstante, ya son corrientes en los sitios de Internet, especialmente los que tienen grandes colecciones de datos. En el presente artículo, voy a presentar técnicas para la construcción de nubes de etiquetas y voy a proponer mecanismos genéricos para soportar distintos tipos de colecciones de datos.

Tres funciones

Una nube de etiquetas (figura 1) es una colección de etiquetas que se presenta de forma que el énfasis visual de cada etiqueta se corresponde con su importancia relativa dentro de la colección. (Dependiendo del contexto, las nubes de etiquetas pueden denominarse también “nubes de texto”, “nubes de tema”, o “nubes de palabras”).

Las nubes de etiquetas ofrecen tres funciones en una única construcción visual:
– Los usuarios pueden buscar fácilmente etiquetas porque los textos están ordenados alfabéticamente.
– Como alternativa (y de forma más espontánea), los usuarios pueden dejar que su navegación dependa de cualquiera entre varias opciones.
– Pero incluso sin navegación, los tamaños de fuente portan una función informativa según la importancia relativa de las distintas etiquetas y el contenido del sitio web.

Figura 1

Tras examinar distintos métodos, llegué a la conclusión que las nubes de etiquetas se implementan normalmente para conjuntos de datos y presentaciones específicos, y considero alternativas para otros tipos de datos y otros diseños de IU. Obviamente, lo que se necesita es un enfoque más genérico.

Aunque no presento aquí una implementación completa de una solución genérica, sí se pueden usar estos ejemplos como punto de inicio para compilar algo mucho mejor que lo que han producido hasta la fecha mis búsquedas en Internet.

El diseño de una nube de etiquetas consiste en varias capas funcionales. La mayoría de las implementaciones que he examinado tratan el acceso a los datos, la lógica comercial, la distribución y la funcionalidad en un trozo de código – a veces incluso en una clase.
Mi propuesta trata cada una de las capas funcionales de forma individual, una a la vez. Para mí, esto hace más fácil implementar alternativas dentro de las arquitecturas. Mis ejemplos están en Visual Basic. NET porque su sintaxis es fácil de entender (especialmente para mí).

Datos fuente

Como input para una nube de etiquetas, necesitamos un conjunto de datos que consisten en al menos tres columnas.
– Texto (para mostrar)
– Peso (para establecer el tamaño de fuente).
– Identificador (algo para soportar la navegación.)

El peso en el conjunto de datos a menudo representa alguna frecuencia – el número de veces que se utiliza un texto como término de búsqueda, o el número de elementos vendidos de un producto. No obstante, el peso no es siempre un valor entero.

Podemos también considerar, por ejemplo, los resultados de una elección que consiste en partidos políticos y sus porcentajes, terremotos y su intensidad, o estrellas de cine y su nivel de inteligencia. De hecho, técnicamente hay poca diferencia entre las nubes de etiquetas, los histogramas, los gráficos de líneas y los gráficos circulares. (No me sorprendería encontrar la nube de etiquetas como otro tipo de gráfico estándar en Excel 2010)

Mientras construimos los datos fuente para una nube de etiquetas, podemos imponer restricciones a los datos en bruto del sistema de tres formas:
– Al igual que con otros gráficos, hay una restricción con la densidad de información en las nubes de etiquetas. Según Wikipedia, las nubes de datos normalmente contienen entre 30 y 150 etiquetas. La usabilidad obviamente establece un límite máximo al número de etiquetas. Lo que es más, la presentación de la página puede imponer una restricción al espacio disponible para la nube de etiquetas. Es por tanto necesario tener en cuenta una longitud máxima impuesta para el conjunto de datos.
– Algunos textos pueden no ser interesantes para los usuarios y deberían omitirse de la nube de etiquetas. Este es el caso para artículos y otras palabras pequeñas que son consideradas como “ruido” por los algoritmos de búsqueda. Si hay etiquetas de este tipo en nuestros datos, es probable que queramos filtrar los resultados.
– Muchas nubes de etiquetas presentan información calculada durante un período de tiempo, como el número de veces que se han utilizado términos de búsqueda durante las últimas 24 horas. Dependiendo de los datos, nuestra función puede contener parámetros extra con los que restringimos la agregación de datos a un sub-conjunto progresivo.

Con el tiempo, crearemos una o más funciones que se parecen al listado número 1. Nuestra arquitectura para el acceso a los datos es, seguramente, más sofisticado que este simple ejemplo. Pero si separamos la construcción de los datos fuente de las restantes capas funcionales de la nube de datos, tendremos ya un diseño mejor que el ejemplo medio de nube de etiquetas que encontramos en Internet.

Listado número 1

Public Function GetWriters(ByVal maxCount As Integer, _

ByVal ignoreNoise As Boolean, ByVal fromDate As DateTime, _

ByVal toDate As DateTime) As DataTable

Dim query As String = String.Format( _

"SELECT * FROM (SELECT TOP 0 ID, Text, " & _

"Count FROM Writers ORDER BY Count DESC) sub " & _

"ORDER BY Text ASC", maxCount)

'TODO: also filter on ignoreNoise, fromDate and toDate

Dim adapter As New SqlDataAdapter(query, _ConnectionString)

Dim table As New DataTable

adapter.Fill(table)

Return table

End Function

Linearización

Con fines ilustrativos, he creado un conjunto de datos de autores famosos en nuestro campo, con el número de resultados que se obtiene con estos nombres en una búsqueda de Google. Cuando uso los datos en bruto para crear una nube de etiquetas, obtengo el resultado de la figura 2(a). La nube de etiquetas presenta la mayoría de los nombres en aproximadamente el mismo tamaño.

Sólo destacan algunos nombres y otros son casi ilegibles. El motivo es que los pesos no están distribuidos de forma equilibrada en la gama de datos fuente. La mayoría de los autores de mi estantería tienen (aproximadamente) el mismo número de resultados Google. Sólo algunos autores tienen o muchísimos o poquísimos resultados. Parece que aquí podemos reconocer una distribución normal (o gaussiana), de la que podemos ver ejemplos en la figura 3

Para conseguir un rango de tamaños de fuente distribuida de forma más equitativa en la nube de etiquetas, hay que “linearizar” los valores originales. Obtendremos mejores resultados si utilizamos una representación linearizada, como en la figura 2(b). Técnicamente, la linearización significa que los pesos se hacen menos exactos. Pero como las etiquetas tienen distintas longitudes de palabra, no hay ya nada de reflejo exacto de los pesos. Aquí estamos interesados en la usabilidad, no en la exactitud.

Figura 2

Linearización de datos fuente.
Figura 3
Distribuciones normales.

También se encuentra con frecuencia la distribución Pareto, o «norma 80-20» (véase la figura 4). En esta distribución, el 80 por ciento de los pesos está en el 20 por ciento del rango más bajo, mientras que el otro 20 por ciento completa el restante 50 por ciento del rango, o vice-versa.

Ejemplos famosos de estratigráfica distribución incluyen riqueza entre personas, popularidad de sitios web y frecuencia de palabras en la lengua inglesa. Hemos de seleccionar el algoritmo adecuado para la linearización de nuestro conjunto de datos.
En la figura 2(c) mi conjunto de datos (que contiene una distribución normal) está linearizado como si contuviera una distribución Pareto. El resultado puede ser extraño si seleccionamos el modelo de distribución equivocado.

Sorprendentemente, he observado que varios autores hacen exactamente lo contrario – linearizaron conjuntos de datos que contenían distribuciones Pareto asumiendo (sin saberlo, me imagino) que eran distribuciones normales. Evidentemente, el conocimiento estadístico en sí no se encuentra distribuido de forma equilibrada entre los desarrolladores de software.

Figura 4

Distribuciones Pareto.

Necesitaremos varias funciones cuando linearizamos múltiples tipos de distribuciones. Cada función sólo necesita una colección de pesos como input, y retorna una nueva versión (linearizada) de la colección. Mi sugerencia es trabajar con interfaces genéricas para colecciones para poder aplicar las mismas funciones a distintos tipos de fuentes de datos.

Hay que especificar límites explícitos superiores e inferiores para el rango deseado de valores de output. También parece adecuado trabajar con números decimales o reales, no enteros. Desde mi punto de vista, los valores a enteros se deberían dejar para el código IU.

El listado número 2 es mi intento de linearizar una distribución normal, que está parcialmente basada en algunos ejemplos de Internet. La función calcula la desviación estándar (sd) y hace la asunción estadísticamente correcta de que casi todos los números estarán dentro del rango -2 * sd a + 2 * sd. Para cada número, se calcula un nuevo peso en una línea recta a lo largo de ese rango.

El listado número 3 presenta un algoritmo que lineariza una distribución Pareto. Esta función calcula un peso nuevo para cada número que usa un logaritmo, con e como el número base. (Los “carcas” entre nosotros no se sentirán satisfechos con esto y pueden establecer a partir de sus propios datos fuente el número base que daría la mejor aproximación.) El resto de la función en este caso también traza los nuevos valores en una línea linear ficticia entre los valores máximo y mínimo.

Listado número 2

Public Shared Function FromBellCurve( _

ByVal weights As ICollection(Of Decimal), _

ByVal minSize As Decimal, ByVal maxSize As Decimal) _

As ICollection(Of Decimal)

'First, calculate the mean weight.

Dim meansum As Decimal = 0

For Each w As Decimal In weights

meansum += w

Next

Dim mean As Double = meansum / weights.Count

'Second, calculate the standard deviation of the weights.

Dim sdsum As Double = 0

For Each w As Decimal In weights

sdsum += (w - mean) ^ 2

Next

Dim sd As Double = ((1 / weights.Count) * sdsum) ^ 0.5

'Now calculate the slope of a straight line from -2*sd to +2*sd.

Dim slope As Double

If sd > 0 Then

slope = (maxSize - minSize) / (4 * sd)

End If

'Get the value in the middle between minSize and maxSize.

Dim middle As Double = (minSize + maxSize) / 2

'Calculate the result for the given deviation from mean.

Dim output As New List(Of Decimal)

For Each w As Decimal In weights

If (sd = 0) Then

'With sd=0 all tags have the same weight.

output.Add(CDec(middle))

Else

'Calculate the distance from mean for this weight.

Dim distance As Double = w – mean

'Calculate the position on the slope for this distance.

Dim result As Double = CDec(slope * distance + middle)

'If the tag turned out too small, set minSize.

If result < minSize Then result = minSize 'If the tag turned out too big, set maxSize. If result > maxSize Then result = maxSize

output.Add(CDec(result))

End If

Next

Return output

End Function

Listado número 3

Public Shared Function FromParetoCurve( _

ByVal weights As ICollection(Of Decimal), _

ByVal minSize As Decimal, ByVal maxSize As Decimal) _

As ICollection(Of Decimal)

'Convert each weight to its log value.

Const BASE As Double = Math.E

Dim logweights As New List(Of Decimal)

For Each w As Decimal In weights

logweights.Add(CDec(Math.Log(w, BASE)))

Next

'First, find the min and max weight.

Dim min As Decimal = Decimal.MaxValue

Dim max As Decimal = Decimal.MinValue

For Each w As Decimal In logweights

If w < min Then min = w If w > max Then max = w

Next

'Now calculate the slope of a straight line, from min to max.

Dim slope As Double

If max > min Then

slope = (maxSize - minSize) / (max - min)

End If

'Get the value in the middle between minSize and maxSize.

Dim middle As Double = (minSize + maxSize) / 2

'Calculate the result for each of the weights.

Dim output As New List(Of Decimal)

For Each w As Decimal In logweights

If (max <= min) Then 'With max=min all tags have the same weight. output.Add(CDec(middle)) Else 'Calculate the distance from the minimum for this weight. Dim distance As Double = w - min 'Calculate the position on the slope for this distance. Dim result As Double = CDec(slope * distance + minSize) 'If the tag turned out too small, set minSize. If result < minSize Then result = minSize 'If the tag turned out too big, set maxSize. If result > maxSize Then result = maxSize

output.Add(CDec(result))

End If

Next

Return output

End Function

Presentación

Para establecer los tamaños de fuente, he encontrado cuatro técnicas (listado número cuatro). Podemos ver que se usan tanto los tamaños de fuente absolutos (url1) como los relativos (url2). Podemos también traducir los pesos a nombres de clase CSS (url3) o a múltiples instancias de etiquetas de tamaño (url4). Sin duda se nos ocurrirán más alternativas de las que queremos soportar para nuestro código.

No abordo aquí cómo crear controles IU o cómo ligar las etiquetas HTML a los datos. Asumo que se pueden tomar ideas de mis ejemplos y convertirlas en un código que funcione. Sólo conviene recordar que los desarrolladores front-end son como mínimo tan testarudos como otros ingenieros de software.

Si nos decidimos por crear nuestro propio control de IU, conviene que pongamos las cosas fáciles a nuestros colegas front-end haciendo que nuestro generador de HTML sea compatible con varias de las técnicas mencionadas. Lo que también se aplica al contexto en el que se colocan los hiperenlaces.

Algunas soluciones usan HTML para enumerar las etiquetas de texto; otras usan espacios para separarlas unas de otras. Cabe la posibilidad de que un diseñador de IU quiera otras propiedades de los hiperenlaces (como la intensidad del color) para variar con el peso de las etiquetas. Un buen control de IU no se interpondrá en el camino de las ideas creativas.

Un último consejo: No olvidemos que cualquier espacio en las etiquetas (como en nombres de autores) puede sustituirse por &nbsp; mientras reproduce el HTML. Eso les ahorra a los desarrolladores front-end el esfuerzo de tomar medidas frente a un envoltorio no deseado de las etiquetas.

Listado número 4

Dim url1 As String = "2"

Dim url2 As String = "2"

Dim url3 As String = "2"

Dim url4 As String = "...2..."

Conclusión

Para resumir, hay distintos tipos de datos que pueden servir como fuentes de datos para las nubes de etiquetas y podemos aplicar algoritmos distintos para distribuir los tamaños de fuente de forma más equilibrada entre las nubes de etiquetas. Al usar esta información podremos compilar una solución genérica en nuestro entorno favorito, que sea aplicable en muchas y distintas situaciones. Con suerte, me encontraré con algunos de los resultados del lector la próxima vez que esté buscando buenas soluciones.

DDJ

Noticias relacionadas

Comentarios

No hay comentarios.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos necesarios están marcados *

Debes haber iniciado sesión para comentar una noticia.