我有以下df:
let giftcardSlider = UIkit.slider('#giftcard-slider', { autoplay: false});
我这样累积AREA列:
df = pd.DataFrame({'ID1':[1,2,3,4,5,6],'ID2':[2,6,6,2,1,2],'AREA':[1,1,1,1,1,1]})
...
ID1 ID2 AREA
0 1 2 1
1 2 6 1
2 3 6 1
3 4 2 1
4 5 1 1
5 6 2 1
对于for id_ in df.ID1:
id1_filter = df.ID1 == id_
id2_filter = (df.ID1 == id_) | (df.ID2 == id_)
df.loc[id1_filter, 'AREA'] = df.loc[id2_filter].AREA.sum()
print(df)
...
ID1 ID2 AREA
0 1 2 2
1 2 6 5
2 3 6 1
3 4 2 1
4 5 1 1
5 6 2 7
中的每个id_
,将ID1
求和,其中AREA
== ID1
或id_
,
并且它始终在ID2 == id_
上对df
进行排序时运行。
尽管我正在处理的实际数据帧是150,000条记录,每一行都属于一个唯一的ID1。
在此数据帧上运行上述操作需要2.5个小时。由于此操作将反复发生
在可预见的将来,我决定将True值的索引存储在ID1
和id1_filter
中
在具有以下架构的数据库中。
表ID1:
id2_filter
表ID2:
ID_,INDEX_
1 , 0
2 , 1
etc, ect
下次我在ID_,INDEX_
1 , 0
1 , 4
2 , 0
2 , 1
2 , 3
2 , 5
etc, etc
列上运行累积(现在已填充了不同的AREA
值)
我读了sql表,并将其转换为字典。然后,我使用这些命令
在求和循环中获取我需要的记录。
AREA
以这种方式运行仅需6分钟!
我的问题:是否有更好/标准的方法来处理这种情况,即存储用于 以后使用?旁注,我在SQL表的ID列上设置了索引,并尝试获取 通过查询表中的每个ID进行索引,效果很好,但仍比上述时间长(9分钟)。
答案 0 :(得分:1)
一种方法是这样的:
df = df.set_index('ID1')
for row in df.join(df.groupby('ID2')['AREA'].apply(lambda x: x.index.tolist()),rsuffix='_').dropna().itertuples():
df.loc[row[0],'AREA'] += df.loc[row[3],'AREA'].sum()
df = df.reset_index()
您将获得预期的结果
ID1 ID2 AREA
0 1 2 2
1 2 6 5
2 3 6 1
3 4 2 1
4 5 1 1
5 6 2 7
现在使用更大的df
,例如:
df = pd.DataFrame( {'ID1':range(1,1501),'ID2': np.random.randint(1,1501,(1500,)),'AREA':[1]*1500},
columns = ['ID1','ID2','AREA'])
当您的第一个方法运行6.5 s时,此处介绍的方法在我的计算机上的运行时间约为0.76 s。
最终,您可以创建一个df_list
,例如:
df_list = (df.set_index('ID1')
.join(df.set_index('ID1').groupby('ID2')['AREA']
.apply(lambda x: x.index.tolist()),rsuffix='_ID2')
.dropna().drop(['AREA','ID2'],1))
将链接ID1和ID2的信息保留在某处:在这里您可以看到ID 2列中的ID等于2,其中ID1的值= 1、4和6
AREA_ID2
ID1
1 [5]
2 [1, 4, 6]
6 [2, 3]
,然后您可以运行以不重新创建df_list
,但代码略有不同:
df = df.set_index('ID1')
for row in df_list.itertuples():
df.loc[row[0],'AREA'] += df.loc[row[1],'AREA'].sum()
df = df.reset_index()
希望它更快