【问题标题】:Sorting data and generating table outputs from CSV file in Python在 Python 中对数据进行排序并从 CSV 文件生成表输出
【发布时间】:2011-05-08 01:08:46
【问题描述】:

假设我有以下 CSV 文件 (subjects.csv)

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

我想找出哪些学生在同一个班级,只关注蒂姆、汤姆和威尔。我将如何在 Python 中配对这些?

蒂姆和威尔一起参加 2 节课。

汤姆和威尔一起上课。

此外,我想将其绘制在如下表所示的表格上,其中在两个轴上都有名称以及一对学生共享的班级数量(名称按字母升序或降序排序) .. 我已经阅读了有关如何为整个 CSV 文件生成表格的信息,但我无法从头开始制作表格,同时从 CSV 文件中剥离列和行..

             Tim        Tom     Will

    Tim   0           0       0

    Tom   0           0       1

    Will     2           0       0

这超出了我的个人技能水平,但我仍然想知道如何去做并尝试理解。

【问题讨论】:

  • 把你的文件扔掉。每个班级有固定数量的学生是不现实的。在一个文件中有不同数量的“名称”列是不明智的。您应该有 2 列,“主题”和“名称”。此外,您的输出表也不现实。一个现实的场景将有数百名或更多学生...... 100 名学生意味着一张包含 10000 个元素的表格,没有人想要在屏幕上打印或滚动浏览。您之前的问题有列 name1、name2、name3。你是在编这些奇怪的文件设计,还是这是一个家庭作业?
  • 我正在制作这些文件,以便我可以使用它们。你说的很有道理。我应该用一个更好的例子,但我只是想了解使用 CSV 文件排序和生成表格。

标签: python csv


【解决方案1】:

您可以创建一个字典,其中包含每个学生所参加的课程:

>>> 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'])}
>>> 

要检查人们一起上多少课,你可以使用 set 的交集方法:

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

正如约翰在 cmets 中提到的,我将名称硬编码到一个列表中,以模仿您上面给出的示例。要查看整个表,您可以从使用 .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 -----
>>> 

【讨论】:

  • 谢谢你。我会研究交集方法,但有没有办法制定一个允许 Python 自动配对名称的脚本?因为如果我向 CSV 添加更多名称,我猜我将不得不再次将每个名称添加到现有代码中。话虽如此,我会完全忽略主题列,因为它不会成为桌子?
  • 您正在使用嵌套的 for 循环为其自身创建一个列表的乘积。要获得对,您可以查看 itertools.product。解析 csv 后获取学生列表。您可以使用 my_dict.keys()
  • -1 [橡皮图章注释] 如果 Python2.x 则以二进制模式打开 csv 文件,否则使用newline=''
  • @NewPython: (1) 你的代码中不应该有任何名字。所有名称都应位于(精心设计的)文件中。 (2)不能忽略主题栏;构建输出表时必不可少;您无法回答诸如“A 和 B 有多少共同学科?”之类的问题。如果您不知道 A 和 B 正在学习什么科目!
  • @DTing:您需要插入像TABLE_NAMES = sorted(D.iterkeys() 这样的行......它的缺失可能是OP认为他需要在他的代码中包含所有名称的原因。
猜你喜欢
  • 1970-01-01
  • 2015-06-14
  • 2023-03-15
  • 2020-03-16
  • 2017-06-23
  • 1970-01-01
  • 2011-08-04
  • 1970-01-01
  • 2017-08-01
相关资源
最近更新 更多