[英]How to create new column based on substrings in other column in a pandas dataframe?
[英]How create a new column based on other rows in pandas dataframe?
我有一个包含 200k 行的数据框,我尝试根据某些条件添加基于其他行的列。 我试图实现它,但花了很多时间(2 小时)。
这是我的代码:
for index in dataset.index:
A_id = dataset.loc[index, 'A_id']
B_id = dataset.loc[index, 'B_id']
C_date = dataset.loc[index, 'C_date']
subset = dataset[
(dataset['A_id'] == A_id) & (dataset['B_id'] == B_id) & (
dataset['C_date'] < C_date)]
dataset.at[index, 'D_mean'] = subset['D'].mean()
dataset.at[index, 'E_mean'] = subset['E'].mean()
我的数据框看起来像这样:
A = [1, 2, 1, 2, 1, 2]
B = [10, 20, 10, 20, 10, 20]
C = ["22-02-2019", "28-02-19", "07-03-2019", "14-03-2019", "21-12-2019", "11-10-2019"]
D = [10, 12, 21, 81, 20, 1]
E = [7, 10, 14, 31, 61, 9]
dataset = pd.DataFrame({
'A_id': A,
'B_id': B,
'C_date': C,
'D': D,
'E': E,
})
dataset.C_date = pd.to_datetime(dataset.C_date)
dataset
Out[27]:
A_id B_id C_date D E
0 1 10 2019-02-22 10 7
1 2 20 2019-02-28 12 10
2 1 10 2019-07-03 21 14
3 2 20 2019-03-14 81 31
4 1 10 2019-12-21 20 61
5 2 20 2019-11-10 1 9
我希望以比我的解决方案更有效的方式获得此结果:
A_id B_id C_date D E D_mean E_mean
0 1 10 2019-02-22 10 7 NaN NaN
1 2 20 2019-02-28 12 10 NaN NaN
2 1 10 2019-07-03 21 14 10.0 7.0
3 2 20 2019-03-14 81 31 12.0 10.0
4 1 10 2019-12-21 20 61 15.5 10.5
5 2 20 2019-11-10 1 9 46.5 20.5
你有想法吗 ?
我们可以使用组合函数来实现这一点,最值得注意的是pd.DataFrame.rolling
来计算移动平均线。
def custom_agg(group):
cols = ['D', 'E']
for col in cols:
name = '{}_mean'.format(col)
group[name] = group[col].shift() \
.rolling(len(group[col]), min_periods=2) \
.mean() \
.fillna(group[col].iloc[0])
group[name].iloc[0] = pd.np.nan
return group
dataset.groupby(['A_id', 'B_id'], as_index=False).apply(custom_agg)
A_id B_id C_date D E D_mean E_mean
0 1 10 2019-02-22 10 7 NaN NaN
1 2 20 2019-02-28 12 10 NaN NaN
2 1 10 2019-07-03 21 14 10.0 7.0
3 2 20 2019-03-14 81 31 12.0 10.0
4 1 10 2019-12-21 20 61 15.5 10.5
5 2 20 2019-11-10 1 9 46.5 20.5
可能有一种更优雅的方法来执行此操作,但是您应该已经看到使用此方法提高了性能。 只需确保C_date
列提前排序,因为它是移动平均线。
我怀疑您在循环中创建子集的成本很高,我的测试表明您的算法以每分钟约 11,000 个索引的速度运行。 我想出了一种替代算法,该算法对数据进行预排序,以便计算子集变得微不足道,并且运行 200k 行随机数据数据集不到 5 分钟。
dataset.sort_values(by=['A_id', 'B_id', 'C_date'], inplace=True)
dataset.reset_index(drop=True, inplace=True)
last_A = None
last_B = None
first_index = -1
for index in dataset.index:
A_id = dataset.loc[index, 'A_id']
B_id = dataset.loc[index, 'B_id']
C_date = dataset.loc[index, 'C_date']
if (last_A != A_id) | (last_B != B_id):
first_index = index
last_A = A_id
last_B = B_id
subset = dataset[first_index:index]
dataset.at[index, 'D_mean'] = subset['D'].mean()
dataset.at[index, 'E_mean'] = subset['E'].mean()
这是使用.apply
的一种方法:
dataset[['D_mean', 'E_mean']] = (dataset
.apply(lambda df: dataset[(dataset['A_id'] == df['A_id']) &
(dataset['B_id'] == df['B_id']) &
(dataset['C_date'] < df['C_date'])
][['D','E']].mean(axis=0), axis=1)
A_id B_id C_date D E D_mean E_mean
0 1 10 2019-02-22 10 7 NaN NaN
1 2 20 2019-02-28 12 10 NaN NaN
2 1 10 2019-07-03 21 14 10.0 7.0
3 2 20 2019-03-14 81 31 12.0 10.0
4 1 10 2019-12-21 20 61 15.5 10.5
5 2 20 2019-11-10 1 9 46.5 20.5
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.