首页 > 解决方案 > 加速 Pandas .apply 函数。计算行数并对其进行操作

问题描述

我有一个庞大的迁徙运动数据库,我编写了一些脚本来从中获取有用的信息,但它真的很慢。正如您将看到的那样,我不是专业的编码员,我想知道如何使这种数据收集更有效。

首先,初始 CSV 数据库的结构如下:

1 行 = 1 人

          Age       Sex      City_start      City_destination  ...

人 1

人 2

......

最终的数据库结构:

         Balance_2004    Balance_2005       ....

城市1

城市2

……

为了计算每个城市和每年的余额,我创建了一个函数,该函数过滤初始数据库以计算 city_destination (INs) 中有多少行具有特定城市,city_start (OUTs) 中有多少行,然后是一个简单的总和来计算余额为输入 - 输出:

 # idb = initial database
 # City1 = pre-existing in final database
 
 def get_balance(city, df):
    ins = idb.City_start[idb.City_start == City1].count()
    outs = idb.City_destination[idb.City_destination == City1].count()
    balance = ins - outs
    return balance

然后使用此函数,我使用 pandas apply 将最终数据库填充为:

# fdb = final database

fdb['Balance_2004'] = idb['City_start'].apply(get_balance, df=idb)

这很好用,最终结果是我所需要的,我总共使用了 42 个应用函数来获取更具体的数据,例如按性别、按年龄组的平衡……但是为了了解这有多慢,我开始了该脚本(具有 42 个函数)45 分钟前仍在运行。

有什么方法可以以一种不那么耗时的方式做到这一点吗?

提前致谢

标签: pythonpandasperformanceapply

解决方案


通过按城市分组,只进行一次此计算可能是有意义的:

def get_balance_all_cities(df):
    df_diff = pd.DataFrame([df.groupby(["City_start"])["Name"].count(),
                            df.groupby(["City_destination"])["Name"].count()]).T
    df_diff.columns = "start", "end"
    df_diff[df_diff.isna()] = 0
    return df_diff.start - df_diff.end

以下是它如何工作的一些示例:

>>> df = pd.DataFrame([("Person 1", "Chicago", "Chicago"), ("Person 2", "New York", "Chicago"), ("Person 3", "Houston", "New York")], columns=["Name", "City_start", "City_destination"])

>>> df
       Name City_start  City_destination
0  Person 1    Chicago           Chicago
1  Person 2   New York           Chicago
2  Person 3    Houston          New York

>>> ins = df.groupby(["City_start"])["Name"].count()
City_start
Chicago     1
Houston     1
New York    1
Name: Name, dtype: int64

>>> outs = df.groupby(["City_end"])["Name"].count()
City_destination
Chicago     2
New York    1
Name: Name, dtype: int64

>>> df_diff = pd.DataFrame([ins, outs]).T
>>> df_diff.columns = "start", "end"
>>> df_diff[df_diff.isna()] = 0
>>> balance = df_diff.start - df_diff.end
Chicago    -1.0
Houston     1.0
New York    0.0
dtype: float64

最后的解决方法是处理在结束或开始期间没有人居住但在其他时间确实居住的城市。


推荐阅读