2011-10-24 10 views
11

Sembra che dovrebbe essere una domanda ovvia, ma i tutorial e la documentazione sugli elenchi non sono disponibili. Molti di questi problemi derivano dalla dimensione dei miei file di testo (centinaia di MB) e dai miei tentativi di ridurli a qualcosa gestibile dal mio sistema. Di conseguenza, sto facendo il mio lavoro in segmenti e ora sto cercando di combinare i risultati.Combinazione di elenchi di dati di frequenza parola

Ho più elenchi di frequenze di parola (~ 40 di esse). Le liste possono essere acquisite tramite Import [] o come variabili generate in Mathematica. Ogni lista appare come il seguente ed è stato generato utilizzando il Tally [] and Sort [] comandi:

{{ "il", 42216}, { "di", 24903}, { "e", 18624 }, {"n", 16850}, {"in",
16164}, {"de", 14930}, {"a", 14660}, {"a", 14175}, {"la", 7347 }, {"era", 6030}, {"l", 5981}, {"le", 5735}, < < 51293 >>, {"mattatoio", 1}, {"abattement", 1}, {"abattagen", 1}, {"abattage", 1}, {"abated", 1}, {"abandonn", 1}, {"abaiss", 1}, {"aback", 1}, {"aase", 1}, {"aaijaut", 1}, {"aaaah", 1}, {"aaa", 1}}

Ecco un esempio del secondo file:

{{ "il", 30419}, { "n", 20414}, { "de", 19956}, { "di", 16262} , {"e",
14488}, {"a", 12726}, {"a", 12635}, {"in", 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}}

Voglio combinarli in modo che i dati di frequenza vengano aggregati: cioè se il secondo file ha 30.419 occorrenze di "the" ed è unito al primo file, dovrebbe restituire che ci sono 72.635 occorrenze (e così via mentre mi muovo attraverso l'intera collezione).

+3

Una domanda strettamente correlata: http://stackoverflow.com/questions/5143575/aggregating-tally-counters –

+0

Anche in qualche modo correlato: http://stackoverflow.com/questions/7749633/time-efficient-partial-inverted -index-building/ –

risposta

10

Sembra che tu abbia bisogno GatherBy.

Supponiamo che il vostro due liste sono chiamati data1 e data2, quindi utilizzare

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

Questo generalizza facilmente a qualsiasi numero di liste, non solo due.

3

Prova ReplaceRepeated.

Unisciti alle liste. Quindi utilizzare

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

Sono sicuro che ci sono modi più veloci. Nella mia modifica ho inserito {a, c1 + c2} alla fine dell'output della regola, per risparmiare un po 'di tempo. – DavidC

+0

Sebbene concettualmente interessante, è molto lento. –

8

Provare a utilizzare una tabella hash, come questo. Prima le cose SET UP:

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

Ora ad esempio freq["safas"] restituisce 0.Poi, se le liste sono definiti come

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}}; 

si può eseguire questo

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

dopo il quale ad esempio

freq["the"] 
(* 
42216 
*) 

e poi l'elenco accanto

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

dopo di che ad es.

freq["the"] 
72635 

pur

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

Funziona molto velocemente! C'è un modo, comunque, di riportare la lista di nuovo con i risultati finali - cioè una lista aggregata di tutti i termini (es. {{"Il", 72635}, {"di", 41165} ...) [può essere in qualsiasi formato] –

+0

@ ian.milligan prova ad esempio questo http: // stackoverflow.it/questions/7165169/picking-specific-symbol-definition-in-mathematica-not-transformation-rules/7169185 # 7169185 – acl

6

C'è un vecchio detto, "se tutto quello che hai è un martello, tutto diventa un chiodo". Quindi, ecco il mio martello: SelectEquivalents.

Questo può essere fatto un po 'più veloce utilizzando SelectEquivalents:

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

Al fine, il primo parametro è ovviamente solo le liste unite, il secondo è quello che stanno raggruppati per (in questo caso il primo elemento), il terzo param rimuove la stringa lasciando solo il conteggio, e il quarto param la rimette insieme con la stringa come #1 ei conteggi in un elenco come #2.

+0

@ ian.milligan, controlla anche [variante di Faysal] (http://stackoverflow.com/questions/4198961/what-is-in-your-mathematica-tool-bag/6245166 # 6245166) di 'SelectEquivalents'. Personalmente, non renderei tutto un 'Opzione', ma la sua variante è estremamente flessibile. E, entrambe le versioni sono più che capaci di far girare gli anelli attorno a "GatherBy". – rcollyer

8

Qui è una diretta funzione di Sow/Reap:

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

Qui è una forma sintetica del metodo di ACL:

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

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

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

Questo sembra essere un po 'più veloce di Codice Szabolcs sul mio sistema:

+0

Inoltre, la forma compatta del metodo di acl è particolarmente intelligente. Ho una domanda, però, nell'implementazione di 'Reap', perché il punto e virgola dopo l'istruzione' Sow'? – rcollyer

+0

@rcollyer questa è una buona domanda. È una vecchia abitudine, ma forse non è una buona abitudine. Mi ricorda visivamente che non sto usando il risultato diretto di quell'espressione e una volta ho pensato che fosse più efficiente, ma non sembra essere il caso. Ha il vantaggio di sopprimere un grande output, che può essere molto lento da formattare anche con il display Skeleton, se dimentico il '[[2]]' dopo 'Reap'. Dovrei considerare l'uso di 'Scan' o' Do' invece. –