在 numpy / pandas 中迭代的更快方法?
Faster way to iterate in numpy / pandas?
我有一个很大的债券组合,我想创建一个 table 以天为索引,以债券为列,以债券的名义为价值。
我需要将每个债券的开始日期之前和终止日期之后的行设为 0。
有没有比这更有效的方法:
[[np.where( (day>=bonds.inception[i]) &
(day + relativedelta(months=+m) >= bonds.maturity[i] ) &
(day <= bonds.maturity[i]),
bonds.principal[i],
0)
for i in range(bonds.shape[0])] for day in idx_d]
输入示例:
id
nom
inception
maturity
38
200
22/04/2022
22/04/2032
87
100
22/04/2022
22/04/2052
输出示例:
day
38
87
21/04/2022
0
0
22/04/2022
100
200
下面的解决方案仍然需要一个循环。我不知道它是否更快,或者你是否发现它清楚,但我会提供它作为替代方案。
创建一个示例数据框(带有一些额外的键用于演示目的):
import pandas as pd
df = pd.DataFrame({'id': [38, 87, 49, 51, 89],
'nom': [200, 100, 150, 50, 250],
'start_date': ['22/04/2022', '22/04/2022', '01/01/2022', '01/05/2022', '23/04/2012'],
'end_date': ['22/04/2032', '22/04/2052', '01/01/2042', '01/05/2042', '23/04/2022']})
df['start_date'] = pd.to_datetime(df['start_date'])
df['end_date'] = pd.to_datetime(df['end_date'])
df = df.set_index('id')
print(df)
这看起来像:
id
nom
start_date
end_date
38
200
2022-04-22 00:00:00
2032-04-22 00:00:00
87
100
2022-04-22 00:00:00
2052-04-22 00:00:00
49
150
2022-01-01 00:00:00
2042-01-01 00:00:00
51
50
2022-01-05 00:00:00
2042-01-05 00:00:00
89
250
2012-04-23 00:00:00
2022-04-23 00:00:00
现在,创建一个新的空白数据框,默认值为 0:
new = pd.DataFrame(data=0, columns=df.index, index=pd.date_range('2022-04-20', '2062-04-22'))
new.index.rename('day', inplace=True)
然后,遍历列(或原始数据帧的索引),选择相关间隔并将列值设置为所选间隔的相关 'nom':
for column in new.columns:
sel = (new.index >= df.loc[column, 'start_date']) & (new.index <= df.loc[column, 'end_date'])
new.loc[sel, column] = df.loc[df.index == column, 'nom'].values
print(new)
这导致:
day
38
87
49
51
89
2022-04-20 00:00:00
0
0
150
50
250
2022-04-21 00:00:00
0
0
150
50
250
2022-04-22 00:00:00
200
100
150
50
250
2022-04-23 00:00:00
200
100
150
50
250
2022-04-24 00:00:00
200
100
150
50
0
...
2062-04-21 00:00:00
0
0
0
0
0
2062-04-22 00:00:00
0
0
0
0
0
[14613 行 x 5 列]
我有一个很大的债券组合,我想创建一个 table 以天为索引,以债券为列,以债券的名义为价值。
我需要将每个债券的开始日期之前和终止日期之后的行设为 0。
有没有比这更有效的方法:
[[np.where( (day>=bonds.inception[i]) &
(day + relativedelta(months=+m) >= bonds.maturity[i] ) &
(day <= bonds.maturity[i]),
bonds.principal[i],
0)
for i in range(bonds.shape[0])] for day in idx_d]
输入示例:
id | nom | inception | maturity |
---|---|---|---|
38 | 200 | 22/04/2022 | 22/04/2032 |
87 | 100 | 22/04/2022 | 22/04/2052 |
输出示例:
day | 38 | 87 |
---|---|---|
21/04/2022 | 0 | 0 |
22/04/2022 | 100 | 200 |
下面的解决方案仍然需要一个循环。我不知道它是否更快,或者你是否发现它清楚,但我会提供它作为替代方案。
创建一个示例数据框(带有一些额外的键用于演示目的):
import pandas as pd
df = pd.DataFrame({'id': [38, 87, 49, 51, 89],
'nom': [200, 100, 150, 50, 250],
'start_date': ['22/04/2022', '22/04/2022', '01/01/2022', '01/05/2022', '23/04/2012'],
'end_date': ['22/04/2032', '22/04/2052', '01/01/2042', '01/05/2042', '23/04/2022']})
df['start_date'] = pd.to_datetime(df['start_date'])
df['end_date'] = pd.to_datetime(df['end_date'])
df = df.set_index('id')
print(df)
这看起来像:
id | nom | start_date | end_date |
---|---|---|---|
38 | 200 | 2022-04-22 00:00:00 | 2032-04-22 00:00:00 |
87 | 100 | 2022-04-22 00:00:00 | 2052-04-22 00:00:00 |
49 | 150 | 2022-01-01 00:00:00 | 2042-01-01 00:00:00 |
51 | 50 | 2022-01-05 00:00:00 | 2042-01-05 00:00:00 |
89 | 250 | 2012-04-23 00:00:00 | 2022-04-23 00:00:00 |
现在,创建一个新的空白数据框,默认值为 0:
new = pd.DataFrame(data=0, columns=df.index, index=pd.date_range('2022-04-20', '2062-04-22'))
new.index.rename('day', inplace=True)
然后,遍历列(或原始数据帧的索引),选择相关间隔并将列值设置为所选间隔的相关 'nom':
for column in new.columns:
sel = (new.index >= df.loc[column, 'start_date']) & (new.index <= df.loc[column, 'end_date'])
new.loc[sel, column] = df.loc[df.index == column, 'nom'].values
print(new)
这导致:
day | 38 | 87 | 49 | 51 | 89 |
---|---|---|---|---|---|
2022-04-20 00:00:00 | 0 | 0 | 150 | 50 | 250 |
2022-04-21 00:00:00 | 0 | 0 | 150 | 50 | 250 |
2022-04-22 00:00:00 | 200 | 100 | 150 | 50 | 250 |
2022-04-23 00:00:00 | 200 | 100 | 150 | 50 | 250 |
2022-04-24 00:00:00 | 200 | 100 | 150 | 50 | 0 |
... | |||||
2062-04-21 00:00:00 | 0 | 0 | 0 | 0 | 0 |
2062-04-22 00:00:00 | 0 | 0 | 0 | 0 | 0 |
[14613 行 x 5 列]