2011-10-24 13 views
11

Parece que debería ser una pregunta obvia, pero los tutoriales y la documentación en las listas no están disponibles. Muchos de estos problemas provienen del tamaño de mis archivos de texto (cientos de MB) y mis intentos de reducirlos a algo manejable por mi sistema. Como resultado, estoy haciendo mi trabajo en segmentos y ahora estoy tratando de combinar los resultados.Combinación de listas de datos de frecuencia de palabra

Tengo varias listas de frecuencia de palabras (~ 40 de ellas). Las listas se pueden tomar a través de Importar [] o como variables generadas en Mathematica. Cada lista aparece de la siguiente y se ha generado utilizando el Tally [] y clasificar [] comandos:

{{ "el", 42216}, { "de", 24903}, { "y", 18624 }, {"n", 16850}, {"in",
16164}, {"de", 14930}, {"a", 14660}, {"to", 14175}, {"la", 7347 }, {"was", 6030}, {"l", 5981}, {"le", 5735}, < < 51293 >>, {"matadero", 1}, {"abattement", 1}, {"abattagen", 1}, {"abattage", 1}, {"abated", 1}, {"abandonn", 1}, {"abaiss", 1}, {"aback", 1}, {"aase", 1}, {"aaijaut", 1}, {"aaaah", 1}, {"aaa", 1}}

Aquí se muestra un ejemplo del segundo archivo:

{{ "el", 30419}, { "n", 20414}, { "de", 19956}, { "de", 16262} , {"y",
14488}, {"a", 12726}, {"a", 12635}, {"en", 11141}, {"la", 10739}, {"et", 9016 }, {"les", 8675}, {"le", 7748}, < < 101032 >>, {"abattement", 1}, {"abattagen", 1}, {"abattage", 1}, { "abated", 1}, {"abandonn", 1}, {"abaiss", 1}, {"aback", 1}, {"aase", 1}, {"aaijaut", 1}, { "aaaah", 1}, {"aaa", 1}}

Quiero combinarlos para que los datos de frecuencia se agreguen: es decir, si el segundo archivo tiene 30,419 apariciones de 'the' y se une al primer archivo, debe devolver que hay 72,635 ocurrencias (y así sucesivamente a medida que muevo a través de toda la colección).

+3

Una pregunta estrechamente relacionada: http://stackoverflow.com/questions/5143575/aggregating-tally-counters –

+0

También algo relacionado: http://stackoverflow.com/questions/7749633/time-efficient-partial-inverted -index-building/ –

Respuesta

10

Suena como que necesita GatherBy.

Supongamos que las dos listas se denominan data1 y data2, a continuación, utilizar

{#[[1, 1]], Total[#[[All, 2]]]} & /@ GatherBy[Join[data1, data2], First] 

Esto generaliza fácilmente a cualquier número de listas, no sólo dos.

3

Probar ReplaceRepeated.

Únete a las listas. Luego use

//. {{f1___, {a_, c1_}, f2___, {a_, c2_}, f3___} -> {f1, f2, f3, {a, c1 + c2}}} 
+0

Estoy seguro de que hay formas más rápidas. En mi edición coloqué {a, c1 + c2} al final de la salida de la regla, para ahorrar un poco de tiempo. – DavidC

+0

Aunque conceptualmente interesante, esto es muy lento. –

8

Pruebe usar una tabla hash, como esta. set las cosas por primera vez:

ClearAll[freq]; 
freq[_] = 0; 

Ahora por ejemplo freq["safas"] devuelve 0.A continuación, si las listas se definen como

lst1 = {{"the", 42216}, {"of", 24903}, {"and", 18624}, {"n", 
    16850}, {"in", 16164}, {"de", 14930}, {"a", 14660}, {"to", 
    14175}, {"la", 7347}, {"was", 6030}, {"l", 5981}, {"le", 
    5735}, {"abattoir", 1}, {"abattement", 1}, {"abattagen", 
    1}, {"abattage", 1}, {"abated", 1}, {"abandonn", 1}, {"abaiss", 
    1}, {"aback", 1}, {"aase", 1}, {"aaijaut", 1}, {"aaaah", 
    1}, {"aaa", 1}}; 
lst2 = {{"the", 30419}, {"n", 20414}, {"de", 19956}, {"of", 
    16262}, {"and", 14488}, {"to", 12726}, {"a", 12635}, {"in", 
    11141}, {"la", 10739}, {"et", 9016}, {"les", 8675}, {"le", 
    7748}, {"abattement", 1}, {"abattagen", 1}, {"abattage", 
    1}, {"abated", 1}, {"abandonn", 1}, {"abaiss", 1}, {"aback", 
    1}, {"aase", 1}, {"aaijaut", 1}, {"aaaah", 1}, {"aaa", 1}}; 

usted puede funcionar esta

Scan[(freq[#[[1]]] += #[[2]]) &, lst1] 

después de lo cual, por ejemplo,

freq["the"] 
(* 
42216 
*) 

y luego la lista siguiente

Scan[(freq[#[[1]]] += #[[2]]) &, lst2] 

después de lo cual por ejemplo,

freq["the"] 
72635 

mientras que todavía

freq["safas"] 
(* 
0 
*) 
+0

¡Esto funciona realmente rápido! ¿Hay alguna forma, sin embargo, de mostrar la lista nuevamente con los resultados finales, es decir, una lista agregada de todos los términos (es decir, {{"the", 72635}, {"of", 41165} ...) [puede ser en cualquier formato] –

+0

@ ian.milligan pruebe, por ejemplo, este http: // stackoverflow.com/questions/7165169/picking-specific-symbol-definitions-in-mathematica-not-transformation-rules/7169185 # 7169185 – acl

6

Hay un viejo refrán, "si todo lo que tienes es un martillo, todo se convierte en un clavo". Entonces, aquí está mi martillo: SelectEquivalents.

Esto se puede hacer un poco más rápido usando SelectEquivalents:

SelectEquivalents[data1~Join~data2, #[[1]]&, #[[2]]&, {#1, Total[#2]}&] 

el fin, el primer parámetro es, obviamente, sólo las listas unidas, la segunda es lo que están agrupados por (en este caso, el primer elemento), el tercer parámetro quita la cadena y deja solo el conteo, y el cuarto parámetro lo vuelve a juntar con la cadena como #1 y los recuentos en una lista como #2.

+0

@ ian.milligan, también echa un vistazo a [la variante de Faysal] (http://stackoverflow.com/questions/4198961/what-is-in-your-mathematica-tool-bag/6245166 # 6245166) of 'SelectEquivalents'. Yo, personalmente, no convertiría todo en una 'Opción', pero su variante es extremadamente flexible. Y, ambas versiones son más que capaces de ejecutar anillos alrededor de 'GatherBy'. – rcollyer

8

Aquí es una directa función Sow/Reap:

Reap[#2~Sow~# & @@@ data1~Join~data2;, _, {#, [email protected]#2} &][[2]] 

Aquí es una forma concisa del método de ACL:

Module[{c}, 
    c[_] = 0; 

    c[#] += #2 & @@@ data1~Join~data2; 

    {#[[1, 1]], #2} & @@@ [email protected]@c 
] 

Esto parece ser un poco más rápido que Código de Szabolcs en mi sistema:

data1 ~Join~ data2 ~GatherBy~ First /. 
    {{{x_, a_}, {x_, b_}} :> {x, a + b}, {x : {_, _}} :> x} 
+0

Además, la forma compacta del método de acl es particularmente inteligente. Sin embargo, tengo una pregunta en la implementación 'Reap', ¿por qué el punto y coma después de la declaración' Sow'? – rcollyer

+0

@rcollyer esa es una buena pregunta. Es un viejo hábito, pero tal vez no sea bueno. Me recuerda visualmente que no estoy usando el resultado directo de esa expresión y una vez pensé que era más eficiente, pero ese no parece ser el caso. Tiene la ventaja de suprimir una salida grande, que puede ser muy lenta de formatear incluso con la pantalla Skeleton, si me olvido de '[[2]]' después de 'Reap'. Debería considerar usar 'Scan' o' Do' en su lugar. –

Cuestiones relacionadas