Python, словари и таблица сопряженности хи-квадрата

Это - проблема, на которой я ломал головы в течение долгого времени, таким образом, любая справка была бы большой. У меня есть файл, который содержит несколько строк в следующем формате (слово, время, когда слово произошло в, и частота документов, содержащих пообещанный в приведенном примере вовремя). Ниже пример того, на что похож inputfile.

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

У меня есть класс Python, ниже которого я раньше создавал 2-D словари для хранения вышеупомянутого файла с помощью в качестве ключа и частоты как значение:

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

Вопрос, который я имею, принадлежит вычислению определенных вещей при итерации по записям в этом 2D словаре. Для каждого Word 'w' каждый раз 't', вычислите:

  1. Количество документов с Word 'w' в течение времени 't'. (a)
  2. Количество документов без Word 'w' в течение времени 't'. (b)
  3. Количество документов с Word 'w' вне времени 't'. (c)
  4. Количество документов без Word 'w' вне времени 't'. (d)

Каждый из объектов выше представляет одну из ячеек таблицы сопряженности хи-квадрата для каждого слова и время. Все они могут быть вычислены в единственном цикле, или они должны быть сделаны по одному?

Идеально, я хотел бы, чтобы вывод был тем, что ниже, где a, b, c, d являются всеми объектами, вычисленными выше:

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

В случае входного файла выше, результат попытки найти таблицу сопряженности для слова 'яблоком' во время '1' был бы (3,2,1,6). Я объясню, как каждая ячейка вычисляется:

  • '3' документы содержат 'яблоко' в течение времени '1'.
  • Существуют '2' документы в течение времени '1', которые не содержат 'яблоко'.
  • Существует '1' документ, содержащий 'яблоко' вне времени '1'.
  • Существует 6 документов вне времени '1', которые не содержат слово 'яблоко' (1+4+1).
1
задан GobiasKoffi 12 June 2010 в 22:56
поделиться

1 ответ

Ваши 4 числа для яблока / 1 в сумме дают 12, что превышает общее количество наблюдений (11)! Есть только 5 документов вне времени «1», в которых нет слова «яблоко».

Вам необходимо разделить наблюдения на 4 непересекающихся подмножества:
a: яблоко и 1 => 3
b: не яблоко и 1 => 2
c: яблоко, а не-1 => 1
d: not-apple and not-1 => 5

Вот код, который показывает один из способов сделать это:

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)

и вот результат:

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
2
ответ дан 2 September 2019 в 23:48
поделиться
Другие вопросы по тегам:

Похожие вопросы: