如何在不使用外部库(例如 Numpy、Pandas)的情况下读取 CSV 文件?

Posted

技术标签:

【中文标题】如何在不使用外部库(例如 Numpy、Pandas)的情况下读取 CSV 文件?【英文标题】:How to read a CSV file without using external libraries (such as Numpy, Pandas)? 【发布时间】:2019-08-19 14:38:47 【问题描述】:

这是面试中经常出现的问题。

我知道如何使用 Pandas 读取 csv 文件。

但是我正在努力寻找一种不使用外部库来读取文件的方法。

Python 是否带有任何有助于读取 csv 文件的模块?

【问题讨论】:

一个数据框可以看作是记录的集合或列的列表。 Numpy(和 pandas)主要是 C 或 Cython 优化以加速处理大型数据帧,但您手动实现所有内容。仅发表评论,因为当前问题相当广泛。 【参考方案1】:

您很可能需要一个库来读取 CSV 文件。虽然您可以自己打开和解析数据,但这将是乏味且耗时的。幸运的是,python 附带了一个标准的 csv 模块,您无需 pip 安装!您可以像这样读取文件:

import csv

with open('file.csv', 'r') as file:
    my_reader = csv.reader(file, delimiter=',')
    for row in my_reader:
        print(row)

这将向您显示每个row 正在作为列表读入。然后您可以根据索引对其进行处理!还有其他读取数据的方法,如https://docs.python.org/3/library/csv.html 所述,其中一种方法将创建字典而不是列表!

更新

你为我截取的项目链接了你的 github

product_id,product_name,aisle_id,department_id
9327,Garlic Powder,104,13
17461,Air Chilled Organic Boneless Skinless Chicken Breasts,35,12
17668,Unsweetened Chocolate Almond Breeze Almond Milk,91,16
28985,Michigan Organic Kale,83,4
32665,Organic Ezekiel 49 Bread Cinnamon Raisin,112,3
33120,Organic Egg Whites,86,16
45918,Coconut Butter,19,13
46667,Organic Ginger Root,83,4
46842,Plain Pre-Sliced Bagels,93,3

将其保存为file.csv 并使用我发布的上述代码运行它。结果:

['product_id', 'product_name', 'aisle_id', 'department_id']
['9327', 'Garlic Powder', '104', '13']
['17461', 'Air Chilled Organic Boneless Skinless Chicken Breasts', '35', '12']
['17668', 'Unsweetened Chocolate Almond Breeze Almond Milk', '91', '16']
['28985', 'Michigan Organic Kale', '83', '4']
['32665', 'Organic Ezekiel 49 Bread Cinnamon Raisin', '112', '3']
['33120', 'Organic Egg Whites', '86', '16']
['45918', 'Coconut Butter', '19', '13']
['46667', 'Organic Ginger Root', '83', '4']
['46842', 'Plain Pre-Sliced Bagels', '93', '3']

这就是您在问题中提出的问题。我不会为你做你的项目,你应该可以从这里开始工作。

【讨论】:

如果我应该只使用输入和输出库怎么办。我可以使用导入 CSV 库吗? @MosaliHarshaVardhanReddy “输入和输出库”是什么意思? csv 带有 csv.reader()csv.writer() 方法。这是否使它有资格成为“输入和输出库”? 而不是使用 CSV 阅读器。我可能必须使用 file.reader("file.csv") 并将其转换为 DataFrame 我很困惑。你想要一个 DataFrame,但你拒绝使用numpy。我不认为你可以同时拥有它......据我所知,DataFrames 是 numpy 特定的。 @MosaliHarshaVardhanReddy 我真的强烈建议您使用csv 模块,除非另有说明(在您的帖子中您只说numpypandas 被排除在外)。然后,您可以使用sqlite3 创建一个 sql 数据库,或者创建一个列表列表或字典列表来表示您的数据以进行分析。我看不出你根本不应该导入任何东西的理由。如果是这种情况,尽管您正在进行一项繁琐且耗时的艰巨项目,并且忽略了 python 的最佳部分:不必为每个程序重新发明***【参考方案2】:

最近我遇到了一个非常相似的问题,在不使用 pandas 的情况下制作数据结构的问题比这个更复杂。这是迄今为止我发现的唯一相关问题。如果我接受这个问题,那么我被问到的是:将产品 ID 作为字典的键,然后将通道和部门 ID 的元组列表作为值(在 python 中)。字典是必需的数据框。当然我不能在 15 分钟内完成(而不是 2 小时内)。 除了 numpy 和 pandas 之外,我很难想到。

我有以下解决方案,一开始也回答了这个问题。可能不理想,但得到了我需要的东西。 希望这也有帮助。

import csv
file =  open('data.csv', 'r')
reader = csv.reader(file)

items = []  # put the rows in csv to a list
aisle_dept_id = []  # to have a tuple of aisle and dept ids
mydict =  # porudtc id as keys and list of above tuple as values in a dictionary

product_id, aisle_id, department_id, product_name = [], [], [], []

for row in reader:
    items.append(row)

for i  in range(1, len(items)):
    product_id.append(items[i][0])
    aisle_id.append(items[i][1])
    department_id.append(items[i][2])
    product_name.append(items[i][3])

for item1, item2 in zip(aisle_id, department_id):
    aisle_dept_id.append((item1, item2))
for item1, item2 in zip(product_id, aisle_dept_id):
    mydict.update(item1: [item2])

有了输出,

mydict:
'9327': [('104', '13')],
 '17461': [('35', '12')],
 '17668': [('91', '16')],
 '28985': [('83', '4')],
 '32665': [('112', '3')],
 '33120': [('86', '16')],
 '45918': [('19', '13')],
 '46667': [('83', '4')],
 '46842': [('93', '3')]

【讨论】:

【参考方案3】:

当一个人的生产环境受到内存的限制时,能够在不导入其他库的情况下读取和管理数据可能会有所帮助。

为了实现这一点,内置的csv 模块完成了这项工作。

import csv

至少有两种方法可以做到这一点:使用csv.Reader() 或使用csv.DictReader()

csv.Reader() 允许您使用索引访问 CSV 数据,是简单 CSV 文件 (Source) 的理想选择。

另一方面,csv.DictReader() 更友好且易于使用,尤其是在处理大型 CSV 文件时 (Source)。

下面是使用csv.Reader()的方法

>>> import csv
>>> with open('eggs.csv', newline='') as csvfile:
...     spamreader = csv.reader(csvfile, delimiter=' ', quotechar='|')
...     for row in spamreader:
...         print(', '.join(row))
Spam, Spam, Spam, Spam, Spam, Baked Beans
Spam, Lovely Spam, Wonderful Spam

下面是使用csv.DictReader()的方法

>>> import csv
>>> with open('names.csv', newline='') as csvfile:
...     reader = csv.DictReader(csvfile)
...     for row in reader:
...         print(row['first_name'], row['last_name'])
...
Eric Idle
John Cleese

>>> print(row)
'first_name': 'John', 'last_name': 'Cleese'

再举个例子,check Real Python's page here。

【讨论】:

【参考方案4】:

有类似的需求并想出了这个解决方案;一个将 csv 转换为 json 的函数(需要 json 以提高可读性并在无需访问 Pandas 的情况下更轻松地查询数据)。如果函数的headers参数为True,则csv的第一行使用json中的keys,否则使用value index作为keys。

from csv import reader as csv_reader

def csv_to_json(csv_path: str, headers: bool) -> list:
  '''Convert data from a csv to json'''
  # store json data
  json_data = []
  
  try:
    with open(csv_path, 'r') as file:
      reader = csv_reader(file)
      # set column names using first row
      if headers:
        columns = next(reader)
      
      # convert csv to json
      for row in reader:
        row_data = 
        for i in range(len(row)):
          # set key names
          if headers:
            row_key = columns[i].lower()
          else: 
            row_key = i
          # set key/value
          row_data[row_key] = row[i]
        # add data to json store 
        json_data.append(row_data)
        
  # error handling
  except Exception as e:
    print(repr(e))
    
  return json_data

给定一个包含以下内容的 csv

+------+-------+------+
| Year | Month | Week |
+------+-------+------+
| 2020 |    11 |   11 |
| 2020 |    12 |   12 |
+------+-------+------+

带有标题的输出是

[
  "year": 2020, "month": 11, "week": 11,
  "year": 2020, "month": 12, "week": 12
]

没有标题的输出是

[
  "0": 2020, "1": 11, "2": 11,
  "0": 2020, "1": 12, "2": 12
]

【讨论】:

以上是关于如何在不使用外部库(例如 Numpy、Pandas)的情况下读取 CSV 文件?的主要内容,如果未能解决你的问题,请参考以下文章

如何在不使用 numpy 的情况下计算 python 中的标准偏差?

python怎么根据权重赋分

高端实战 Python数据分析与机器学习实战 Numpy/Pandas/Matplotlib等常用库

如何在不使用 Python 中的外部库的情况下解析 arff 文件

在不安装的情况下导入 Python 库

浅谈python的第三方库——pandas