Algoritmo de datos "sin clasificar" / homogeneidad

8

En un intento por no reinventar una rueda, pregunto si alguien tiene ideas sobre un algoritmo de homogeneidad de datos. Un breve ejemplo:

Mis datos tienen varios elementos tal vez como

  1. Número
  2. Color
  3. Fruta
  4. Carta

Hay alrededor de 100 de estos elementos en una matriz. El algoritmo necesita ordenar los elementos para que las 2 entradas con el mismo número se separen tanto como sea posible, y lo mismo con el color, la fruta, etc. También sería bueno si pudiera priorizar los elementos. Parece que nunca alcanzaría el 100%, por lo que le daría varios pases para hacer, verificaría el resultado y luego probaría más pases.

No me sorprendería si hay algo aquí que simplemente funciona que no tengo suficiente google-fu para encontrar.

ExoByte
fuente
¿Has probado algo como la búsqueda genética ?
David Weiser
3
Escribes como un hablante nativo de inglés, así que trabaja un poco en la redacción. Elimina la palabra "me gusta" donde no pertenece y pule tus oraciones en general. Además, ¿te gustaría dar un ejemplo? No he entendido completamente tu pregunta.
Trabajo
3
Los ejemplos son esenciales. Un caso de prueba de unidad es crítico para este tipo de cosas. Un párrafo de texto no es un caso de prueba.
S.Lott

Respuestas:

2

Esto me molestó por un tiempo, así que tuve que ir a ver si estaba resuelto. Aquí está mi idea. Desde cero, no es una aplicación de ningún algoritmo que yo sepa. Este sería un algoritmo de fuerza bruta bastante costoso, pero debería ser bastante efectivo. Se supone que está tratando con el conjunto de datos realmente pequeño que describió (100 filas de 4 columnas) y está trabajando en una computadora moderna con suficiente ram.

Descripción general : Utilizamos un algoritmo recursivo en una lista ordenada para dispersar registros similares a su distancia máxima dentro de registros similares. Después de cada llamada, todos los registros con el mismo padre están a su máxima distancia. La llamada superior incluye todos los registros. Por lo tanto, se clasifica de adentro hacia afuera.

Estructuras de datos :

  • newIndexeses un array<integer>. El índice de la matriz es el índice existente de la fila. El valor será el nuevo índice, comienza con -1
  • dataes un array<array<string>>. La clave es el índice, la matriz interna es una representación de cadena de los valores en una fila. No necesita ser una cadena si tiene alguna forma de agrupar sus datos. El primer elemento de matriz es el que tiene el mayor peso.

Ordenar datapor orden de peso. Ordénelo primero por la columna con mayor peso, dentro de eso por columna con el segundo mayor peso, etc. El resultado es el inverso de lo que desea. Indice secuencialmente.

Aquí está el algoritmo (en psudocódigo).

        // siblingCount: On first call is the number of rows in the table,
    //    on recursive calls it is the number of elements with the same parent
    // index: the index of current row in `data` - starts 0
    // depth: The element index - starts 0
    void unsort(int siblingCount, int index, int depth)
    {
        int count = 1;
        string hash = concatColumns(index, depth + 1);
        while ((index + count < data.count) && (hash == concatColumns(index + count, depth + 1)))
        {
            count++;
        }

        if (depth < columnCount)
            unsort(count, index, depth);
        else if (index < data.count)
            unsort(count, index + count, 0);

        int spacing = siblingCount / count;

        for (int i = 0; i < count; i++)
        {
            var offset = 0;
            while ((newIndexes[index + i + offset] > -1) & (index + i + offset + 1 < newIndexes.count))
                offset++;

            if (newIndexes[index + i + offset] > -1) throw new Exception("Shouldn't happen.");

            newIndexes[index + i + offset] = index + spacing * i;
        }
    }

    string concatColumns(int index, int count) // returns count columns concatinated
    {
        // 1,1 = "1"
        // 1,2 = "1, blue"
        // 1,3 = "1, blue, apple"
        return "1, blue, apple";
    } 

Luego aplique newIndexes a los datos que se van a ordenar.

Reflexiones sobre el enfoque: no probé esto, pero el almacenamiento de los nuevos índices y la resolución de conflictos pueden ser problemáticos ya que los primeros índices se asignan en función de las columnas menos significativas, por lo que si hay muchos conflictos, las columnas significativas más grandes pueden agruparse. Podría intentar aplicar el desplazamiento como positivo primero, luego negativo. O posiblemente haga una especie de inserción en una lista vinculada en lugar de una matriz.

Jim McKeeth
fuente
Ah! Muy veo lo que estás haciendo aquí. Ordenar, luego segregar según el tamaño de la cadena de igualdad. Si esto no funciona directamente, debería estar bastante cerca. ¡Gracias por su ayuda y la limpieza de la pregunta! Espero poder probar esto la próxima vez que necesite procesar este tipo de datos en septiembre.
ExoByte
Déjame saber cómo funciona.
Jim McKeeth
4

Eso me recuerda un algoritmo de red que he visto, la palabra clave 'tkwikibrowser' 'TouchGraphWikiBrowser', donde los elementos se combinan con una especie de banda elástica, pero son como imanes del mismo pol.

No sé cuál sería la mecánica, tirando de su caso, pero tal vez 'caso' es la palabra clave correcta: los elementos se colocan en un caso, se alejan del borde del caso y se alejan entre sí , más aún, si tienen múltiples atributos en común.

Comienzan en posiciones aleatorias, y se mueven dependiendo de la distancia al muro, y de la distancia a elementos similares, y buscan una posición estable.

La fórmula para alejarse entre sí podría ser lineal o cuadrática a la distancia, y podría buscar una buena fórmula en vivo, manipulando los valores.

actualizar:

Para el poder de atracción, simplemente podría tomar la inversa del poder de distracción. Entonces, si 2 Elements no comparten un solo atributo, esta sería la atracción máxima.

usuario desconocido
fuente
OK, voy a morder. Hice una búsqueda en Google en tkwikibrowser y no obtuve nada. ¿Puedes vincular a más información?
Jim McKeeth
Tienes razón, lo siento, el nombre no era TKWiki ..., sino TGWiki ... para TouchGraph, como aquí , pero solo encontré esta captura de pantalla, no una demostración funcional, donde los nodos se mueven como en una banda de goma .
usuario desconocido
3

Utilice una combinación aleatoria u ordene por un hash de los datos concatenados: un buen hash proporciona resultados muy diferentes para entradas similares, por lo que las entradas que son similares en cualquier dimensión deben separarse.

Jon Purdy
fuente
1
Esta parece ser la solución más fácil, pero ahora tengo curiosidad por saber cómo funcionaría con datos del mundo real.
TheLQ
Problema con eso, mientras que el hash similar es diferente, el hash de filas idénticas produciría el mismo hash y luego se ordenaría como adyacente.
Jim McKeeth
Y habrá duplicados exactos en los datos. Sin embargo, este podría ser un lugar interesante para comenzar.
ExoByte
@ Jim McKeeth: Tienes razón. Por supuesto, también puede concatenar un índice para hacer filas idénticas distintas por un pequeño número de bits. También puede buscar curvas de orden Z (obtenidas trivialmente por intercalación de bits), que distribuyen datos lineales espacialmente de manera que los datos cercanos permanecen así. Estás buscando una permutación que ofrezca lo contrario de eso.
Jon Purdy