بيثون ، القواميس ، وطاولة طوارئ تشي مربع
-
26-09-2019 - |
سؤال
هذه مشكلة كنت أرفع أدمغتي لفترة طويلة ، لذلك ستكون أي مساعدة رائعة. لديّ ملف يحتوي على عدة خطوط بالتنسيق التالي (كلمة ، وقت حدثت الكلمة ، وتواتر المستندات التي تحتوي على الكلمة المعطاة في المثال المحدد في الوقت المناسب). فيما يلي مثال على شكل الإدخال.
#inputfile
<word, time, frequency>
apple, 1, 3
banana, 1, 2
apple, 2, 1
banana, 2, 4
orange, 3, 1
لدي فئة بيثون أدناه اعتدت على إنشاء قواميس ثنائية الأبعاد لتخزين الملف أعلاه باستخدام المفتاح ، والتردد كقيمة:
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
السؤال الذي لدي يتعلق بحساب أشياء معينة أثناء التكرار على الإدخالات في هذا القاموس ثنائي الأبعاد. لكل كلمة 'w' في كل مرة 't' ، احسب:
- عدد المستندات معكلمة "ث" داخل الوقت 't'. (أ)
- عدد المستندات بدونكلمة "ث" داخل الوقت 't'. (ب)
- عدد المستندات معكلمة "ث" الخارج الوقت 't'. (ج)
- عدد المستندات بدونكلمة "ث" الخارج الوقت 't'. (د)
يمثل كل عنصر من العناصر أعلاه إحدى خلايا جدول الطوارئ CHI-Square لكل كلمة ووقت. هل يمكن حساب كل هذه الأشياء داخل حلقة واحدة أو هل يجب القيام بها في وقت واحد؟
من الناحية المثالية ، أود أن يكون الإخراج ما هو أدناه ، حيث A ، B ، C ، D كلها العناصر المحسوبة أعلاه:
print "%s, %s, %s, %s" %(a,b,c,d)
في حالة ملف الإدخال أعلاه ، ستكون نتيجة محاولة العثور على جدول الطوارئ لكلمة "Apple" في الوقت "1" (3,2,1,6)
. سأشرح كيف يتم حساب كل خلية:
- تحتوي المستندات "3" على "Apple" خلال الوقت "1".
- هناك وثائق "2" خلال الوقت "1" لا تحتوي على "Apple".
- يوجد مستند "1" يحتوي على "Apple" خارج الوقت "1".
- هناك 6 مستندات خارج الوقت "1" لا تحتوي على كلمة "Apple" (1+4+1).
المحلول
أضف أرقامك الأربعة لـ Apple/1 ما يصل إلى 12 ، أكثر من إجمالي عدد الملاحظات (11)! لا يوجد سوى 5 مستندات خارج الوقت "1" لا تحتوي على كلمة "Apple".
تحتاج إلى تقسيم الملاحظات إلى 4 مجموعات فرعية مفككة:
ج: Apple و 1 => 3
ب: غير التطبيق و 1 => 2
C: Apple وليس 1 => 1
D: غير التطبيق وليس 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