Pregunta

Este es un problema que he devanado los sesos durante mucho tiempo, por lo que cualquier ayuda sería grande. Tengo un archivo que contiene varias líneas en el siguiente formato (Word, momento en que la palabra se produjo en, y la frecuencia de los documentos que contienen la palabra dada en el ejemplo dado en el tiempo). A continuación se muestra un ejemplo de lo que las miradas InputFile similares.

#inputfile
<word, time, frequency>
apple, 1, 3
banana, 1, 2
apple, 2, 1
banana, 2, 4
orange, 3, 1

Tengo clase de Python a continuación que he utilizado para crear diccionarios 2-D para almacenar el archivo anterior utilizando como clave, y la frecuencia como el valor:

class Ddict(dict):
    '''
    2D dictionary class
    '''
    def __init__(self, default=None):
            self.default = default

    def __getitem__(self, key):
            if not self.has_key(key):
                self[key] = self.default()
            return dict.__getitem__(self, key)


wordtime=Ddict(dict) # Store each inputfile entry with a <word,time> key
timeword=Ddict(dict) # Store each inputfile entry with a <time,word> key

# Loop over every line of the inputfile
for line in open('inputfile'):
    word,time,count=line.split(',')

    # If <word,time> already a key, increment count
    try:
        wordtime[word][time]+=count
    # Otherwise, create the key
    except KeyError:
        wordtime[word][time]=count

    # If <time,word> already a key, increment count     
    try:
        timeword[time][word]+=count
    # Otherwise, create the key
    except KeyError:
        timeword[time][word]=count

La pregunta que tengo pertenece a calcular ciertas cosas, mientras que la iteración en las entradas de este diccionario 2D. Para cada palabra 'w' en cada tiempo 't', calcular:

  1. El número de documentos palabra 'w' dentro de tiempo 't'. (A)
  2. El número de documentos sin palabra 'w' dentro de tiempo 't'. (B)
  3. El número de documentos palabra 'w' fuera tiempo 't'. (C)
  4. El número de documentos sin palabra 'w' fuera tiempo 't'. (D)

Cada uno de los elementos anterior representa una de las celdas de una tabla de contingencia de chi-cuadrado para cada palabra y el tiempo. ¿Puede todo esto ser calculado dentro de un solo bucle o necesitan ser uno hecho a la vez?

Idealmente, me gustaría que la salida sea lo que está por debajo, donde a, b, c, d son todos los elementos calculados anteriormente:

print "%s, %s, %s, %s" %(a,b,c,d)

En el caso del archivo de entrada anterior, el resultado de tratar de encontrar la tabla de contingencia para la palabra 'manzana' en el momento '1' sería (3,2,1,6). Voy a explicar cómo se calcula cada celda:

  • '3' documentos contienen 'manzana' dentro de tiempo '1'.
  • Hay '2' documentos dentro del tiempo '1' que no contienen 'manzana'.
  • No es '1' documento que contenga 'Manzana' tiempo fuera '1'.
  • Hay 6 documentos tiempo fuera '1' que no contienen la palabra 'Manzana' (1 + 4 + 1).
¿Fue útil?

Solución

Sus 4 números para la manzana 1 add / hasta 12, más que el número total de observaciones (11)! Hay 5 documentos fuera del tiempo '1' que no contienen la palabra 'manzana'.

Es necesario particionar las observaciones en 4 subconjuntos disjuntos:
R: manzana y 1 => 3
b: no-manzana y 1 => 2
c: manzana y no-1 => 1 | d: no-manzana y no-1 => 5

Aquí hay un código que muestra una manera de hacerlo:

from collections import defaultdict

class Crosstab(object):

    def __init__(self):
        self.count = defaultdict(lambda: defaultdict(int))
        self.row_tot = defaultdict(int)
        self.col_tot = defaultdict(int)
        self.grand_tot = 0

    def add(self, r, c, n):
        self.count[r][c] += n
        self.row_tot[r] += n
        self.col_tot[c] += n
        self.grand_tot += n

def load_data(line_iterator, conv_funcs):
    ct = Crosstab()
    for line in line_iterator:
        r, c, n = [func(s) for func, s in zip(conv_funcs, line.split(','))]
        ct.add(r, c, n)
    return ct

def display_all_2x2_tables(crosstab):
    for rx in crosstab.row_tot:
        for cx in crosstab.col_tot:
            a = crosstab.count[rx][cx]
            b = crosstab.col_tot[cx] - a
            c = crosstab.row_tot[rx] - a
            d = crosstab.grand_tot - a - b - c
            assert all(x >= 0 for x in (a, b, c, d))
            print ",".join(str(x) for x in (rx, cx, a, b, c, d))

if __name__ == "__main__":

    # inputfile
    # <word, time, frequency>
    lines = """\
    apple, 1, 3
    banana, 1, 2
    apple, 2, 1
    banana, 2, 4
    orange, 3, 1""".splitlines()

    ct = load_data(lines, (str.strip, int, int))
    display_all_2x2_tables(ct)

y aquí está la salida:

orange,1,0,5,1,5
orange,2,0,5,1,5
orange,3,1,0,0,10
apple,1,3,2,1,5
apple,2,1,4,3,3
apple,3,0,1,4,6
banana,1,2,3,4,2
banana,2,4,1,2,4
banana,3,0,1,6,4
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top