Gen*_*ius 7 python dataframe pandas
什么是在给定的DataFrame中查找相同行的索引而不迭代各行的pandas方法?
虽然有可能找到所有唯一的行,unique = df[df.duplicated()]然后在这些唯一的条目上迭代并借助unique.iterrows()提取相同条目的索引,pd.where()但是大熊猫的做法是什么?
示例: 给定以下结构的DataFrame:
| param_a | param_b | param_c
1 | 0 | 0 | 0
2 | 0 | 2 | 1
3 | 2 | 1 | 1
4 | 0 | 2 | 1
5 | 2 | 1 | 1
6 | 0 | 0 | 0
Run Code Online (Sandbox Code Playgroud)
输出:
[(1, 6), (2, 4), (3, 5)]
Run Code Online (Sandbox Code Playgroud)
对所有重叠行使用参数duplicated,keep=False然后groupby按所有列使用参数,并将索引值转换为元组,最后将输出转换Series为list:
df = df[df.duplicated(keep=False)]
df = df.groupby(df.columns.tolist()).apply(lambda x: tuple(x.index)).tolist()
print (df)
[(1, 6), (2, 4), (3, 5)]
Run Code Online (Sandbox Code Playgroud)
如果你还想看到重写值:
df1 = (df.groupby(df.columns.tolist())
.apply(lambda x: tuple(x.index))
.reset_index(name='idx'))
print (df1)
param_a param_b param_c idx
0 0 0 0 (1, 6)
1 0 2 1 (2, 4)
2 2 1 1 (3, 5)
Run Code Online (Sandbox Code Playgroud)
方法#1
这是一种矢量化方法,其灵感来自this post-
def group_duplicate_index(df):
a = df.values
sidx = np.lexsort(a.T)
b = a[sidx]
m = np.concatenate(([False], (b[1:] == b[:-1]).all(1), [False] ))
idx = np.flatnonzero(m[1:] != m[:-1])
I = df.index[sidx].tolist()
return [I[i:j] for i,j in zip(idx[::2],idx[1::2]+1)]
Run Code Online (Sandbox Code Playgroud)
样本运行 -
In [42]: df
Out[42]:
param_a param_b param_c
1 0 0 0
2 0 2 1
3 2 1 1
4 0 2 1
5 2 1 1
6 0 0 0
In [43]: group_duplicate_index(df)
Out[43]: [[1, 6], [3, 5], [2, 4]]
Run Code Online (Sandbox Code Playgroud)
方法#2
对于整数编号的数据帧,我们可以将每一行减少为一个标量,这让我们可以使用数组1D,从而为我们提供一个性能更高的数组,如下所示 -
def group_duplicate_index_v2(df):
a = df.values
s = (a.max()+1)**np.arange(df.shape[1])
sidx = a.dot(s).argsort()
b = a[sidx]
m = np.concatenate(([False], (b[1:] == b[:-1]).all(1), [False] ))
idx = np.flatnonzero(m[1:] != m[:-1])
I = df.index[sidx].tolist()
return [I[i:j] for i,j in zip(idx[::2],idx[1::2]+1)]
Run Code Online (Sandbox Code Playgroud)
运行时测试
其他方法 -
def groupby_app(df): # @jezrael's soln
df = df[df.duplicated(keep=False)]
df = df.groupby(df.columns.tolist()).apply(lambda x: tuple(x.index)).tolist()
return df
Run Code Online (Sandbox Code Playgroud)
时间安排 -
In [274]: df = pd.DataFrame(np.random.randint(0,10,(100000,3)))
In [275]: %timeit group_duplicate_index(df)
10 loops, best of 3: 36.1 ms per loop
In [276]: %timeit group_duplicate_index_v2(df)
100 loops, best of 3: 15 ms per loop
In [277]: %timeit groupby_app(df) # @jezrael's soln
10 loops, best of 3: 25.9 ms per loop
Run Code Online (Sandbox Code Playgroud)