从 CSV 行创建自定义对象

Create custom objects from CSV rows

我有以下 CSV 文件:

id;area;zz;nc
1;35.66;2490.8;1
2;65.35;2414.93;1
3;79.05;2269.33;1
4;24.5;2807.68;1
5;19.31;2528.59;1
6;25.51;2596.44;1

其中每一行代表一个所谓的 Cell 对象及其 id、area、zz、cc。

因此,我创建了以下 class:

class cells():
    #    
    # Initializer / Instance Attributes
    def __init__(self, idm, area,zz,nc):
        self.idm  = idm
        self.area = area

想法是创建多个对象作为单元格的数量,并根据文件中的数据为它们分配属性。

我的第一个想法是将 csv 文件作为 DataFrame 读取,然后循环填充对象列表。

据我所知,python 的循环效率很低,我想知道是否有另一种方法(聪明的方法)来做到这一点。

谢谢, 迭戈

我不太明白你所说的循环是什么意思,但这将为你拥有的每一行创建一个单元格对象列表 - 考虑到你的数据所处的格式。

Pandas 对序列的列表理解是一个合理的选择,参见

试试这个:

import pandas as pd 


class Cell():
    # Initializer / Instance Attributes
    def __init__(self, idm, area, zz, nc):
        self.idm  = idm
        self.area = area


def create_cells(row):
    newcell = Cell(row[0], row[1], row[2], row[3])
    return newcell


file = pd.read_table("your_file.csv", sep=';')
zipp = zip(file['id'], file['area'], file['zz'], file['nc'])
cells = [create_cells(row) for row in zipp]

print(cells)

我不知道您为 df 的每一行使用对象 Cells 的目的。但是,我认为您可以使用 df.agg 实现它并将每个对象保持在一个系列中

class Cells():
    # Initializer / Instance Attributes
    def __init__(self, idm, area, zz, nc):
        self.idm  = idm
        self.area = area
        self.zz = zz
        self.nc = nc

s = df.agg(lambda x: Cells(*x), axis=1)
print(s)

Output:
0    <__main__.Cells object at 0x09FA38D0>
1    <__main__.Cells object at 0x09FA3510>
2    <__main__.Cells object at 0x09FA3870>
3    <__main__.Cells object at 0x09FA3AF0>
4    <__main__.Cells object at 0x09B27790>
5    <__main__.Cells object at 0x09B27770>
dtype: object

之后您可以通过 s

的索引访问每个对象
In [303]: s[0].__dict__
Out[303]: {'idm': 1.0, 'area': 35.66, 'zz': 2490.8, 'nc': 1.0}

In [304]: s[1].__dict__
Out[304]: {'idm': 2.0, 'area': 65.35, 'zz': 2414.93, 'nc': 1.0}

uMdRupert 在他的回答中分享了一个 link 到一个有趣的 post,我建议你去看看!


我喜欢他使用列表理解的想法,所以我想分享一个类似的方法:

import pandas as pd


class Cell:
    def __init__(self, idm, area, zz, nc):
        self.idm = idm
        self.area = area


cell_df = pd.read_csv('../resources/test_cell_data.csv', delimiter=';')
cell_df = cell_df.rename({'id': 'idm'}, axis='columns')

cell_objs_lst = [Cell(*curr_tuple._asdict()) for curr_tuple in cell_df.itertuples(index=False)]

Pandas 对于这个任务来说可能有点矫枉过正,所以这里有一个使用 csv 模块的非常简单的方法:

import csv


class Cell:
    def __init__(self, idm, area, zz, nc):
        self.idm = idm
        self.area = area


with open('../resources/test_cell_data.csv', newline='') as in_file:
    next(in_file)
    reader = csv.DictReader(in_file, fieldnames=['idm', 'area', 'zz', 'nc'], delimiter=';')
    cells_lst = [Cell(**curr_row) for curr_row in reader]

我认为在这种情况下您不需要 pandas。如果您只需要读取一个 csv 文件,pandas 就太过分了。

要么直接阅读:

objects = []
next(f) # skip header row
with open('your_file', 'r') as f:
    for row in f:
        objects.append(cells(*row.strip().split(';')))

或使用 csv 模块。