我编写了一个程序来读取几个 .csv 文件(它们并不大,每个文件几千行),我进行了一些数据清理和整理,这是每个 .csv 文件的最终结构(虚假数据仅供说明之用)。
import pandas as pd
data = [[112233, 'Rob', 99], [445566, 'John', 88]]
managers = pd.DataFrame(data)
managers.columns = ['ManagerId', 'ManagerName', 'ShopId']
print managers
ManagerId ManagerName ShopId
0 112233 Rob 99
1 445566 John 88
data = [[99, 'Shop1'], [88, 'Shop2']]
shops = pd.DataFrame(data)
shops.columns = ['ShopId', 'ShopName']
print shops
ShopId ShopName
0 99 Shop1
1 88 Shop2
data = [[99, 2000, 3000, 4000], [88, 2500, 3500, 4500]]
sales = pd.DataFrame(data)
sales.columns = ['ShopId', 'Year2010', 'Year2011', 'Year2012']
print sales
ShopId Year2010 Year2011 Year2012
0 99 2000 3000 4000
1 88 2500 3500 4500
然后我使用 xlsxwriter
和 reportlab
Python 包在迭代数据框的同时创建自定义 Excel 工作表和 .pdf 报告。一切看起来都很棒,所有命名的包都很好地完成了它们的工作。
但我担心的是,我觉得我的代码很难维护,因为我需要在多次调用中多次访问相同的数据框行。
假设我需要获取负责 2010 年销售额超过 1500 的商店的经理姓名。我的代码充满了这种调用:
managers[managers['ShopId'].isin(
sales[sales['Year2010'] > 1500]['ShopId'])]['ManagerName'].values
>>> array(['Rob', 'John'], dtype=object)
我认为在阅读这行代码时很难看出发生了什么。我可以创建多个中间变量,但这会添加多行代码。
牺牲数据库规范化思想并将所有部分合并到一个数据框架中以获得更易于维护的代码有多常见?拥有单个数据框显然有缺点,因为在尝试合并以后可能需要的其他数据框时,它可能会变得困惑。合并它们当然会导致数据冗余,因为同一位经理可能被分配到多个商店。
df = managers.merge(sales, how='left', on='ShopId').
merge(shops, how='left', on='ShopId')
print df
ManagerId ManagerName ShopId Year2010 Year2011 Year2012 ShopName
0 112233 Rob 99 2000 3000 4000 Shop1
1 445566 John 88 2500 3500 4500 Shop2
至少这个调用变小了:
df[df['Year2010'] > 1500]['ManagerName'].values
>>> array(['Rob', 'John'], dtype=object)
也许 pandas 是这种工作的错误工具?
办公室的 C# 开发人员对我皱眉并告诉我使用这些类,但我会有一堆方法,如 get_manager_sales(managerid)
等等。为报告迭代类实例听起来也很麻烦,因为我需要实现一些排序和索引(我通过 pandas
免费获得)。
字典可以工作,但它也使修改现有数据、进行合并等变得困难。语法也没有变得更好。
data_dict = df.to_dict('records')
[{'ManagerId': 112233L,
'ManagerName': 'Rob',
'ShopId': 99L,
'ShopName': 'Shop1',
'Year2010': 2000L,
'Year2011': 3000L,
'Year2012': 4000L},
{'ManagerId': 445566L,
'ManagerName': 'John',
'ShopId': 88L,
'ShopName': 'Shop2',
'Year2010': 2500L,
'Year2011': 3500L,
'Year2012': 4500L}]
获取负责 2010 年销售额超过 1500 的商店的经理姓名。
[row['ManagerName'] for row in data_dict if row['Year2010'] > 1500]
>>> ['Rob', 'John']
在我处理数据的这种特殊情况下,我应该一直使用 pandas
还是有另一种方法来编写更清晰的代码,同时利用 的强大功能> Pandas
?
最佳答案
我会选择 Pandas,因为它速度更快,具有优秀且极其丰富的 API,源代码看起来更干净更好,等等。
顺便说一句,下面这行可以很容易地重写:
managers[managers['ShopId'].isin(sales[sales['Year2010'] > 1500]['ShopId'])]['ManagerName'].values
作为:
ShopIds = sales.ix[sales['Year2010'] > 1500, 'ShopId']
managers.query('ShopId in @ShopIds')['ManagerName'].values
IMO 它很容易阅读和理解
PS 你可能还想将数据存储在支持 SQL
的数据库中并使用 SQL 或将其存储在 HDF Store 中并使用 where
参数 - 在这两种情况下您可以从索引“搜索”列中受益
关于python - 在 pandas、OOP 类和字典之间进行选择 (Python),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40041845/