在数据帧中对重复列ID进行分组

现在有很多类似的问题,但大多数都回答了如何删除重复的列。但是,我想知道如何创建一个元组列表,其中每个元组包含重复列的列名。我假设每列都有一个唯一的名称。为了进一步说明我的问题:

数据帧({‘A’:[1,2,3,4,5],’B’:[2,4,2,1,9],
‘C’:[1,2,3,4,5],‘D’:[2,4,2,1,9],
‘E’:[3,4,2,1,2],‘F’:[1,1,1,1]},
索引=[‘a1’,’a2’,’a3’,’a4’,’a5’])

然后我想要输出:

[('A','C'),('B','D')]

如果你今天感觉很好,那么同样的问题也可以延伸到行。如何获取每个元组包含重复行的元组列表

这里有一个简单的方法-

def组重复列(df):
a=df.0值
sidx=np.lexsort(a)
b=a[:,sidx]
m=np.连接(([False],(b[:,1::==b[:,:-1])。全部(0),[False]))
idx=np.flatnonzero(m[1::!=m[:-1])
C=df.columns[sidx].tolist()
返回[C[i:j]表示i,j在zip中(idx[::2],idx[1::2]+1)]

样本运行-

[100]on

:df
Output[100]:
A B C D E F
a1 1 2 1 2 3 1
a2 2 4 4 1
a3 3 2 3 2 1
a4 4 1 4 1 1 1
a5 5 9 5 9 2 1
[101]on:组重复列(df)
Out[101]:[[A',C',['B',D']]
#让我们在包含“A”的组中再添加一个副本
In[102]:df.F=df.A
[103]on:组重复列(df)
Out[103]:[[A',C',F',['B',D']]

转换为执行相同的操作,但是对于行(索引),我们只需要沿着另一个轴切换操作,如下所示-

def组重复行(df):
a=df.0值
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])
C=df.index[sidx].tolist()
返回[C[i:j]表示i,j在zip中(idx[::2],idx[1::2]+1)]

样本运行-

[260]on

:df2
Output[260]:
a1 a2 a3 a4 a5
35 34 5
B 1 1
C3 5 3 4 5
D 2 9 2 1 9
E 2 2 1 2
F1
[261]on:分组重复行(df2)
Out[261]:[['B','F',['A','C']]

基准测试

接近-

#@John Galt's soln-1
从itertools导入组合
def组合应用程序(df):
如果(df[x[0]==df[x[-1]]),则在组合(df.columns,2)中为x返回[x]。all()
#@Abdou's soln
def pandas_groupby_应用程序(df):
如果len(d)>1,则返回[df.T.groupby(list(df.T.columns))中d的元组(d.index)]
#@COLDSPEED's soln
def triu_应用程序(df):
c=df.columns.tolist()
i、 j=np.triu_指数(len(c),1)
x=[(c[\u i],c[\u j])表示_i,如果(df[c[\u i]]==df[c[\u j]]),则压缩(i,j)中的_j。all()
返回x
#@cmaher's soln
def lambda_set_应用程序(df):
返回列表(筛选器(lambda x:len(x)>1,列表(set([tuple([x代表df.columns中的x,如果所有(df[x]==df[y]))代表df.columns中的y]))

注:@John Galt的soln-2不包括在内,因为输入的大小(8000500)将随着该输入的拟议广播而爆炸

时间安排-

[179]on

:#使用问题中提到的大小设置输入
…:df=pd.DataFrame(np.random.randint(0,10,(8000500)))
…:df.columns=['C'+str(i)表示范围内的i(df.shape[1])]
…:idx0=np.random.choice(df.shape[1],df.shape[1]//2,replace=0)
…:idx1=np.random.choice(df.shape[1],df.shape[1]//2,replace=0)
…:df.iloc[:,idx0]=df.iloc[:,idx1].值
...: 
#@John Galt的soln-1
At[180]:%timeit组合_应用程序(df)
1个回路,最佳3个:每个回路24.6秒
#@Abdou's soln
At[181]on:%timeit pandas\u groupby\u应用程序(df)
1圈,最佳3圈:每圈3.81秒
#@COLDSPEED's soln
At[182]:%timeit triu_应用程序(df)
1个回路,最佳3个:每个回路25.5秒
#@cmaher's soln
At[183]on:%timeit lambda_set_app(df)
1圈,最佳3圈:每个圈27.1秒
#在这个职位上提议
At[184]on:%timeit group\u duplicate\u cols(df)
10个回路,最佳3个:每个回路188毫秒

使用NumPy的查看功能进行超级增强

利用NumPy的视图功能,可以将每组元素视为一个数据类型,我们可以获得更显著的性能提升,如下所示-

def view1D(a):#a是数组
a=np.ASCONTIGOUUSARRAY(a)
void_dt=np.dtype((np.void,a.dtype.itemsize*a.shape[1]))
返回a.view(void_dt).ravel()
def组副本冷却液v2(df):
a=df.0值
sidx=view1D(a.T).argsort()
b=a[:,sidx]
m=np.连接(([False],(b[:,1::==b[:,:-1])。全部(0),[False]))
idx=np.flatnonzero(m[1::!=m[:-1])
C=df.columns[sidx].tolist()
返回[C[i:j]表示i,j在zip中(idx[::2],idx[1::2]+1)]

时间安排-

[322]on

:%timeit组\u重复\u列(df)
10个回路,最佳3个:每个回路185毫秒
At[323]on:%timeit组\u重复\u列\u v2(df)
10个回路,最佳3个:69.3 ms/回路

只是疯狂的加速

发表评论