我有一个很大的df我需要改变。对于一个计算,我想将数据分组到pborderid上,然后只保留to_wpadr中具有重复值的行。
这是我的df的一个例子。
pborderid pbcarid wsid to_wpadr colli pk_end_time
10 76079450 61838497 hp1 523-369p 1 2016-07-01 00:00:38
11 76079450 61838504 hp1 523-370p 1 2016-07-01 00:00:47
12 76079450 61838110 hp1 523-372p 1 2016-07-01 00:01:05
13 76079450 61838225 hp1 523-372p 2 2016-07-01 00:01:13
14 76079450 61838504 hp1 523-372p 3 2016-07-01 00:01:30
15 76079450 61838497 hp1 523-373p 1 2016-07-01 00:01:45
16 76079450 61838504 hp1 523-377p 1 2016-07-01 00:01:55
17 76079450 61838110 hp1 523-376p 5 2016-07-01 00:02:26
18 76079450 61838225 hp1 523-376p 1 2016-07-01 00:02:33
19 76079450 61838497 hp1 523-376p 6 2016-07-01 00:02:55
使用以下代码可以正常工作,但是当组数增加时,性能会显着降低,最多需要20秒。我认为应该只使用pborderid作为组然后过滤/应用。
ap=ot.groupby(["pborderid","to_wpadr"],sort=False).filter(lambda x: len(x) >1)
任何人都有任何建议我怎么只能使用一个组列或者我如何才能提高性能呢?
这是想要的结果:
pborderid pbcarid wsid to_wpadr colli pk_end_time
12 76079450 61838110 hp1 523-372p 1 2016-07-01 00:01:05
13 76079450 61838225 hp1 523-372p 2 2016-07-01 00:01:13
14 76079450 61838504 hp1 523-372p 3 2016-07-01 00:01:30
17 76079450 61838110 hp1 523-376p 5 2016-07-01 00:02:26
18 76079450 61838225 hp1 523-376p 1 2016-07-01 00:02:33
19 76079450 61838497 hp1 523-376p 6 2016-07-01 00:02:55
答案 0 :(得分:2)
我不知道它是否会更快,但您可以尝试使用DataFrame.duplicated
仅过滤重复项。
ap = ot[ot.duplicated(subset=['pborderid', 'to_wpadr'], keep=False)]
针对1M行的时间DF:
In [244]: df = pd.concat([df] * 10**5, ignore_index=True)
In [245]: %timeit df.groupby(["pborderid","to_wpadr"],sort=False).filter(lambda x: len(x) >1)
1 loop, best of 3: 313 ms per loop
In [246]: %timeit df[df.duplicated(subset=['pborderid', 'to_wpadr'], keep=False)]
10 loops, best of 3: 129 ms per loop
In [247]: df.shape
Out[247]: (1000000, 6)
答案 1 :(得分:0)
受this solution
的启发,我们也可以在这种情况下替换groupby
操作。实现看起来像这样 -
# Create numerical IDs for relevant columns and a combined one
ID1 = np.unique(df['pborderid'],return_inverse=True)[1]
ID2 = np.unique(df['to_wpadr'],return_inverse=True)[1]
ID = np.column_stack((ID1,ID2))
# Convert to linear indices
lidx = np.ravel_multi_index(ID.T,ID.max(0)+1)
# Get unique IDs for each element based on grouped uniqueness and group counts
_,ID,count = np.unique(lidx,return_inverse=True,return_counts=True)
# Look for counts>1 and collect respective IDs and thus respective rows off df
df_out = df[np.in1d(ID,np.where(count>1)[0])]
示例运行 -
In [233]: df
Out[233]:
pborderid to_wpadr values
0 ID0 John 3
1 ID1 Erick 8
2 ID1 John 3
3 ID1 Mandy 5
4 ID0 Erick 9
5 ID1 Mandy 4
6 ID0 John 6
7 ID1 John 1
In [234]: df_out
Out[234]:
pborderid to_wpadr values
0 ID0 John 3
2 ID1 John 3
3 ID1 Mandy 5
5 ID1 Mandy 4
6 ID0 John 6
7 ID1 John 1
我的运行时测试似乎没有表明这种方法比其他解决方案中列出的groupby
方法有任何改进。所以,似乎df.groupby
似乎是首选方式!