用矢量化方法替换python for循环以丢弃丢失的d

2024-03-29 02:06:59 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在努力进行数据清理操作。我有一个很大的数据框,由id、portfolio months(port\u months)和portfolio number(port)组成,例如:

                id          port      port_months backtest_month
49025        USA0EBZ0         0            1             1
80689        USA0EBZ0         0            2             2
224952       USA0EBZ0         0            3             4
  ...           ...          ...          ... 
227370       USA03BE0         1            1             12
229804       USA03BE0         1            2             13
232262       USA03BE0         1            3             14
  ...           ...          ...          ...

不幸的是,我经常遇到这样一种情况,即新id进入系统时数据不完整,例如:

                id          port      port_months backtest_month
63682        USA06W90         5            7           66
236452       USA06W90         5            8           67
238905       USA06W90         5            9           68
241358       USA06W90         5           10           69
243808       USA06W90         5           11           70
246229       USA06W90         5           12           71

这里的问题是这个id的数据进入数据帧的位置是port_months = 7,而不是port_months = 1。我需要删除所有这些不完整的数据,因为另一个函数需要对只包含完整数据的数据集执行操作。因此,在这个例子中,我需要删除端口=5的这个id USA06W90的数据(虽然您在这里看不到它,但是有端口=6的完整数据,以此类推)。你知道吗

我已经写了一个简单的循环,它做了我想要的,但它是难以置信的慢,我相信有一些更复杂的,我可以用矢量化:

for id in df.id:
    for port in df.port.unique(): #so loop over ports where the current stock has some data, not those for which it is absent from the system
        first_df = df[(df.id == id) & (df.port == port) & (df.port_months == 1)] #get the 1st row from the current port's dataframe
        if first_df.empty:
            df.drop(df[(df.id == id) & (df.port == port)].index, inplace = True) # drop all the rows associated with current id and port (i.e. all port_months for current port and id)

这是目前远远超过30分钟执行!你知道吗

我一直在想聪明的使用方法

groupby('id', port).apply(lambda x: x.port = x[x.port_months == 1].port)

或者什么的,或者试图用一些诡计来构建新的投资组合并做ffill

port_new = df[df.port_months == 1].groupby('id', as_index = False).apply(lambda x: x.backtest_month / 12 )

重置索引,然后通过在索引上合并来与df重新组合

这将提供:

                id          port      port_months backtest_month
49025        USA0EBZ0         0            1             1
80689        USA0EBZ0         NaN          2             2
224952       USA0EBZ0         NaN          3             4
  ...           ...          ...          ... 
227370       USA03BE0         1            1             12
229804       USA03BE0         NaN          2             13
232262       USA03BE0         NaN          3             14
  ...           ...          ...          ...

然后可以使用

df.fillna['port_new'](method = 'ffill')

这几乎可以正常工作,而且发光很快,但问题是您遇到了这样的情况:一个id进入数据集,然后又离开数据集,因此ffill也会填充所有这些nas,而不是删除行,例如下面的NAN将填充5s

例如

                id          port      port_months backtest_month
63682        USA06W90         5            11           70
236452       USA06W90         5            12           71
238905       USA06W90       NaN             1           121
241358       USA06W90       NaN             2           122
243808       USA06W90       NaN             3           123
246229       USA06W90       NaN             4           124

Tags: the数据iddfforportcurrentnan
1条回答
网友
1楼 · 发布于 2024-03-29 02:06:59

要生成独特的投资组合,似乎需要创建一个由idport组成的键。然后可以使用.loc高效地进行过滤,如下所示:

df = pd.DataFrame({'backtest_month': [70, 71, 121, 122, 123],
                   'id': ['USA06W90', 'USA06W90', 'USA06W90', 'USA06W90', 'USA06W90'],
                   'port': [5, 5, 1, 1, 1],
                   'port_months': [11, 12, 1, 2, 3]})

>>> df
              id  port  port_months  backtest_month         key
63682   USA06W90     5           11              70  USA06W90_5
236452  USA06W90     5           12              71  USA06W90_5
238905  USA06W90     1            1             121  USA06W90_1
241358  USA06W90     1            2             122  USA06W90_1
243808  USA06W90     1            3             123  USA06W90_1

#  Create a unique portfolio identifier.
df['key'] = df['id'] + '_' + df.port.astype(str)

# Use .loc to locate all unique portfolios that had a `port_months` value of one.
portfolios_first_month = df.loc[df.port_months == 1, 'key'].unique()
>>> portfolios_first_month
array(['USA06W90_1'], dtype=object)

# Use .loc again to locate all portfolio keys that were previously identified above.  
# The colon indicates that all columns should be returned.
df_filtered = df.loc[df.key.isin(portfolios_first_month), :]

>>> df_filtered
              id  port  port_months  backtest_month         key
238905  USA06W90     1            1             121  USA06W90_1
241358  USA06W90     1            2             122  USA06W90_1
243808  USA06W90     1            3             123  USA06W90_1

它生成一个包含所有唯一密钥的数组,其中port\u months的值为1(即没有丢失的数据)。你知道吗

df.loc[df.key.isin(portfolios_first_month), :]然后定位所有这些键值并返回数据帧中的所有列。你知道吗

相关问题 更多 >