在pandas,OOP类和dicts(Python)之间进行选择

Ale*_*kov 8 python oop dictionary class pandas

我编写了一个程序,它读取了几个.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
Run Code Online (Sandbox Code Playgroud)

然后我使用xlsxwriterreportlabPython包在迭代数据帧时创建自定义Excel工作表和.pdf报告.一切看起来都很棒,所有命名的包都能很好地完成它们的工作.

我担心的是我觉得我的代码难以维护,因为我需要在多次调用中多次访问相同的数据帧行.

假设我需要获得负责2010年销售额超过1500的商店的经理名称.我的代码充满了这种调用:

managers[managers['ShopId'].isin(
    sales[sales['Year2010'] > 1500]['ShopId'])]['ManagerName'].values
>>> array(['Rob', 'John'], dtype=object)
Run Code Online (Sandbox Code Playgroud)

我认为在阅读这行代码时很难看到发生了什么.我可以创建多个中间变量,但这会添加多行代码.

牺牲数据库规范化意识形态并将所有部分合并到一个数据框中以获得更易维护的代码有多常见?显然有一个单一数据框的缺点,因为在尝试合并稍后可能需要的其他数据帧时它可能会变得混乱.合并它们当然会导致数据冗余,因为同一个经理可以分配到多个商店.

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
Run Code Online (Sandbox Code Playgroud)

至少这个调用会变小:

df[df['Year2010'] > 1500]['ManagerName'].values
>>> array(['Rob', 'John'], dtype=object)
Run Code Online (Sandbox Code Playgroud)

也许熊猫是这种工作的错误工具?

办公室里的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}]
Run Code Online (Sandbox Code Playgroud)

获取经理名称,负责2010年销售额超过1500的商店.

[row['ManagerName'] for row in data_dict if row['Year2010'] > 1500]
>>> ['Rob', 'John']
Run Code Online (Sandbox Code Playgroud)

在我操作的数据的这种特殊情况下,我应该一直使用pandas还是有另一种方法来编写更干净的代码,同时利用它的强大功能pandas

Max*_*axU 4

我会选择 Pandas,因为它速度更快,拥有优秀且极其丰富的 API,源代码看起来更干净、更好,等等。

顺便说一句,以下行可以轻松重写:

managers[managers['ShopId'].isin(sales[sales['Year2010'] > 1500]['ShopId'])]['ManagerName'].values
Run Code Online (Sandbox Code Playgroud)

作为:

ShopIds = sales.ix[sales['Year2010'] > 1500, 'ShopId']
managers.query('ShopId in @ShopIds')['ManagerName'].values
Run Code Online (Sandbox Code Playgroud)

IMO 它很容易阅读和理解

PS,您可能还希望将数据存储在SQL可用的数据库中并使用 SQL 或将其存储在 HDF 存储中并使用where参数 - 在这两种情况下,您都可以从索引“搜索”列中受益