在Python中从CSV文件排序数据并生成表格输出

2 投票
1 回答
2564 浏览
提问于 2025-04-16 17:12

假设我有一个这样的CSV文件(subjects.csv)

subjects,name1,name2,name3
Chemistry,Tom,Will,Rob
Biology,Megan,Sam,Tim
Physics,Tim,Will,Bob
Maths,Will,Tim,Joe

我想找出哪些学生是同班同学,主要关注Tim、Tom和Will。我该如何在Python中把他们配对呢?

比如说:

Tim和Will一起上了2门课。

Tom和Will一起上了1门课。

此外,我还想把这些信息放在一个表格里,像我下面写的那样,表格的两边都是名字,里面是每对学生共同上课的数量(名字可以按字母顺序排列)。我看过怎么为整个CSV文件生成表格,但我还是搞不懂怎么从头开始制作表格,同时又要从CSV文件中去掉一些列和行……

             Tim        Tom     Will

    Tim   0           0       0

    Tom   0           0       1

    Will     2           0       0

这超出了我个人的能力范围,但我还是想知道怎么做,并试着理解一下。

1 个回答

4

你可以创建一个字典,里面记录每个学生正在上哪些课:

>>> import csv
>>> import collections
>>> D = collections.defaultdict(set)
>>> with open('subjects.csv','rb') as f:
...     subject_reader = csv.reader(f)
...     header = subject_reader.next()
...     for row in subject_reader:
...         for name in row[1:]:
...             D[name].add(row[0])
... 
>>> import pprint
>>> pprint.pprint(dict(D))
{'Bob': set(['Physics']),
 'Joe': set(['Maths']),
 'Megan': set(['Biology']),
 'Rob': set(['Chemistry']),
 'Sam': set(['Biology']),
 'Tim': set(['Biology', 'Maths', 'Physics']),
 'Tom': set(['Chemistry']),
 'Will': set(['Chemistry', 'Maths', 'Physics'])}
>>> 

如果想检查有多少人一起上课,可以使用集合的交集方法:

>>> D['Tom'].intersection(D['Will'])
set(['Chemistry'])
>>> len(_)
1
>>> D['Tim'].intersection(D['Will'])
set(['Maths', 'Physics'])
>>> len(_)
2
>>> 

要打印出你例子中的表格,可以这样做:

>>> EXAMPLE_NAMES = ['Tom','Tim','Will']
>>> for y_name in EXAMPLE_NAMES:
...     print '{0:{width}}'.format(y_name,width=5),
...     for x_name in EXAMPLE_NAMES:
...         if y_name==x_name:
...             print '{0:{width}}'.format('-'*5, width=5),
...         else:
...             print '{0:{width}}'.format(len(D[y_name].intersection(D[x_name])), width=5),
...     print
... 
Tom   -----     0     1
Tim       0 -----     2
Will      1     2 -----

表格的标题可能看起来像这样:

    >>> for x_name in [' ']+EXAMPLE_NAMES:
    ...     print '{0:{width}}'.format(x_name, width=5),
    ... 
          Tom   Tim   Will 

正如约翰在评论中提到的,我把名字硬编码到一个列表里,以模拟你上面给的例子。要查看整个表格,你可以获取或遍历你创建的字典中的键,使用 .iterkeys().keys()

>>> import csv
>>> import collections
>>> 
>>> my_d = collections.defaultdict(set)
>>> with open('subjects.csv','rb') as f:
...     subject_reader = csv.reader(f)
...     header = subject_reader.next()
...     for row in subject_reader:
...         for name in row[1:]:
...             my_d[name].add(row[0])
... 
>>> def display_header(D):
...     for x_name in [' ']+D.keys():
...         print '{0:{width}}'.format(x_name, width=5),
...     print
... 
>>> def display_body(D):
...     for y_name in D.iterkeys():
...         print '{0:{width}}'.format(y_name,width=5),
...         for x_name in D.iterkeys():
...             if y_name==x_name:
...                 print '{0:{width}}'.format('-'*5, width=5),
...             else:
...                 print '{0:{width}}'.format(len(D[y_name].intersection(D[x_name])), width=5),
...         print
... 
>>> def display_table(D):
...     display_header(D)
...     display_body(D)
... 
>>> display_table(my_d)
      Sam   Rob   Megan Will  Tim   Joe   Tom   Bob  
Sam   -----     0     1     0     1     0     0     0
Rob       0 -----     0     1     0     0     1     0
Megan     1     0 -----     0     1     0     0     0
Will      0     1     0 -----     2     1     1     1
Tim       1     0     1     2 -----     1     0     1
Joe       0     0     0     1     1 -----     0     0
Tom       0     1     0     1     0     0 -----     0
Bob       0     0     0     1     1     0     0 -----
>>> 

撰写回答