当前位置: 首页 > 面试题库 >

在pandas数据框中分组重复的列ID

邴兴为
2023-03-14
问题内容

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

df = pd.DataFrame({'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, 1]},
                   index = ['a1', 'a2', 'a3', 'a4', 'a5'])

然后我想要输出:

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

如果今天您感觉很好,则将相同的问题扩展到行。如何获取元组列表,其中每个元组都包含重复的行。


问题答案:

这是NumPy的一种方法-

def group_duplicate_cols(df):
    a = df.values
    sidx = np.lexsort(a)
    b = a[:,sidx]

    m = np.concatenate(([False], (b[:,1:] == b[:,:-1]).all(0), [False] ))
    idx = np.flatnonzero(m[1:] != m[:-1])
    C = df.columns[sidx].tolist()
    return [C[i:j] for i,j in zip(idx[::2],idx[1::2]+1)]

样品运行-

In [100]: df
Out[100]: 
    A  B  C  D  E  F
a1  1  2  1  2  3  1
a2  2  4  2  4  4  1
a3  3  2  3  2  2  1
a4  4  1  4  1  1  1
a5  5  9  5  9  2  1

In [101]: group_duplicate_cols(df)
Out[101]: [['A', 'C'], ['B', 'D']]

# Let's add one more duplicate into group containing 'A'
In [102]: df.F = df.A

In [103]: group_duplicate_cols(df)
Out[103]: [['A', 'C', 'F'], ['B', 'D']]

进行转换即可,但是对于rows(index),我们只需要沿另一条轴切换操作,就像这样-

def group_duplicate_rows(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])
    C = df.index[sidx].tolist()
    return [C[i:j] for i,j in zip(idx[::2],idx[1::2]+1)]

样品运行-

In [260]: df2
Out[260]: 
   a1  a2  a3  a4  a5
A   3   5   3   4   5
B   1   1   1   1   1
C   3   5   3   4   5
D   2   9   2   1   9
E   2   2   2   1   2
F   1   1   1   1   1

In [261]: group_duplicate_rows(df2)
Out[261]: [['B', 'F'], ['A', 'C']]

标杆管理

方法-

# @John Galt's soln-1
from itertools import combinations
def combinations_app(df):
    return[x for x in combinations(df.columns, 2) if (df[x[0]] == df[x[-1]]).all()]

# @Abdou's soln
def pandas_groupby_app(df):
    return [tuple(d.index) for _,d in df.T.groupby(list(df.T.columns)) if len(d) > 1]

# @COLDSPEED's soln
def triu_app(df):
    c = df.columns.tolist()
    i, j = np.triu_indices(len(c), 1)
    x = [(c[_i], c[_j]) for _i, _j in zip(i, j) if (df[c[_i]] == df[c[_j]]).all()]
    return x

# @cmaher's soln
def lambda_set_app(df):
    return list(filter(lambda x: len(x) > 1, list(set([tuple([x for x in df.columns if all(df[x] == df[y])]) for y in df.columns]))))

注意:@John Galt's soln-2未包括在内,因为输入的大小(8000,500)会与针对该输入的提议不符broadcasting

时间-

In [179]: # Setup inputs with sizes as mentioned in the question
     ...: df = pd.DataFrame(np.random.randint(0,10,(8000,500)))
     ...: df.columns = ['C'+str(i) for i in range(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].values
     ...:

# @John Galt's soln-1
In [180]: %timeit combinations_app(df)
1 loops, best of 3: 24.6 s per loop

# @Abdou's soln
In [181]: %timeit pandas_groupby_app(df)
1 loops, best of 3: 3.81 s per loop

# @COLDSPEED's soln
In [182]: %timeit triu_app(df)
1 loops, best of 3: 25.5 s per loop

# @cmaher's soln
In [183]: %timeit lambda_set_app(df)
1 loops, best of 3: 27.1 s per loop

# Proposed in this post
In [184]: %timeit group_duplicate_cols(df)
10 loops, best of 3: 188 ms per loop

借助NumPy的视图功能实现超级助推

借助NumPy的视图功能,我们可以将每组元素视为一个dtype,这样可以进一步提高性能,如下所示-

def view1D(a): # a is array
    a = np.ascontiguousarray(a)
    void_dt = np.dtype((np.void, a.dtype.itemsize * a.shape[1]))
    return a.view(void_dt).ravel()

def group_duplicate_cols_v2(df):
    a = df.values
    sidx = view1D(a.T).argsort()
    b = a[:,sidx]

    m = np.concatenate(([False], (b[:,1:] == b[:,:-1]).all(0), [False] ))
    idx = np.flatnonzero(m[1:] != m[:-1])
    C = df.columns[sidx].tolist()
    return [C[i:j] for i,j in zip(idx[::2],idx[1::2]+1)]

时间-

In [322]: %timeit group_duplicate_cols(df)
10 loops, best of 3: 185 ms per loop

In [323]: %timeit group_duplicate_cols_v2(df)
10 loops, best of 3: 69.3 ms per loop

只是疯狂的加速!



 类似资料:
  • 问题内容: 这是我的数据框,应重复5次: 我想要这样的结果: 但是必须有一种比保持追加更聪明的方法。实际上,Im正在处理的数据帧应重复50次。 我还没有发现任何实用的东西,包括类似-—的东西,但它在数据框架上不起作用。 有人可以帮忙吗? 问题答案: 您可以使用以下功能: 如果只想重复值而不是索引,则可以执行以下操作:

  • 问题内容: 我想在中设置多列的(我有一个文件,我不得不手动将其解析为列表列表,因为该文件不适合) 我懂了 我可以设置它们的唯一方法是循环遍历每个列变量并使用重铸。 有没有更好的办法? 问题答案: 从0.17开始,您必须使用显式转换: (如下所述,在0.17中已不再使用“魔术”了) 您可以将它们应用于要转换的每一列: 并确认dtype已更新。 适用于大熊猫0.12-0.16的旧/建议答案:您可以用来

  • 问题内容: 给定一个记录某些书籍使用情况的数据框,如下所示: 我需要获取所有书籍的数量,保留其他列并获取以下内容: 如何才能做到这一点? 谢谢! 问题答案: 您需要以下内容: 在您的情况下,“名称”,“类型”和“ ID”列的值匹配,因此我们可以对它们进行调用,然后单击。 另一种方法是使用添加“ Count”列,然后调用:

  • 问题内容: 我有一个具有此类数据的数据框(列过多): 列看起来像这样: 我想像这样将列中的所有值转换为整数: 我通过以下方法解决了这一问题: 现在,我的数据框中有两列-旧列和新列,需要删除旧列。 那是不好的做法。它是可行的,但是在我的数据框中有很多列,我不想手动进行。 pythonic如何巧妙地实现呢? 问题答案: 首先,要将“分类”列转换为其数字代码,可以使用以下命令更轻松地做到这一点。 此外,

  • 问题内容: 这应该很容易,但是以某种方式我找不到有效的解决方案。 我有一个熊猫数据框,看起来像这样: 我想按col1和col2分组并获得col3和col4。 由于无法汇总数据,因此可以删除。 这是输出的样子。我很感兴趣,同时具有和中产生的数据帧。是否和是否属于索引并不重要。 这是我尝试过的: 但是,这只会返回的汇总结果。 我在这里迷路了。我发现的每个示例仅汇总一列,显然不会发生此问题。 问题答案:

  • 问题内容: 如果数据如下所示: 我想复制IsHoliday等于TRUE的行,我可以这样做: 但是是否有更好的方法来执行此操作,因为我需要将假日行重复5次,如果使用上述方法,则必须追加5次。 问题答案: 您可以放入列表中,然后执行以下操作: