繁体   English   中英

Pandas:根据多个列值删除行

[英]Pandas: Delete rows based on multiple columns values

我有一个包含A,B,C列的数据框。 我有一个像[(x1,y1), (x2,y2), ...]这样的元组列表。 我想删除满足以下条件的所有行: (B=x1 && C=y1) | (B=x2 && C=y2) | ... (B=x1 && C=y1) | (B=x2 && C=y2) | ... (B=x1 && C=y1) | (B=x2 && C=y2) | ...我怎么能在熊猫里做到这一点? 我想使用isin函数,但不确定是否可以,因为我的列表中有元组。 我可以这样做:

for x,y in tuples:   
    df = df.drop(df[df.B==x && df.C==y].index)

也许有一种更简单的方法。

使用pandas索引

df.set_index(list('BC')).drop(tuples, errors='ignore').reset_index()

定时

def linear_indexing_based(df, tuples):
    idx = np.array(tuples)
    BC_arr = df[['B','C']].values
    shp = np.maximum(BC_arr.max(0)+1,idx.max(0)+1)
    BC_IDs = np.ravel_multi_index(BC_arr.T,shp)
    idx_IDs = np.ravel_multi_index(idx.T,shp)
    return df[~np.in1d(BC_IDs,idx_IDs)]

def divakar(df, tuples):
    idx = np.array(tuples)
    mask = (df.B.values == idx[:, None, 0]) & (df.C.values == idx[:, None, 1])
    return df[~mask.any(0)]

def pirsquared(df, tuples):
    return df.set_index(list('BC')).drop(tuples).reset_index()

10行,1元组

np.random.seed([3,1415])
df = pd.DataFrame(np.random.choice(range(10), (10, 3)), columns=list('ABC'))
tuples = [tuple(row) for row in np.random.choice(range(10), (1, 2))]

在此输入图像描述

10,000行,500元组

np.random.seed([3,1415])
df = pd.DataFrame(np.random.choice(range(10), (10000, 3)), columns=list('ABC'))
tuples = [tuple(row) for row in np.random.choice(range(10), (500, 2))]

在此输入图像描述

方法#1

这是使用NumPy's broadcasting的矢量化方法 -

def broadcasting_based(df, tuples):
    idx = np.array(tuples)
    mask = (df.B.values == idx[:, None, 0]) & (df.C.values == idx[:, None, 1])
    return df[~mask.any(0)]

样品运行 -

In [224]: df
Out[224]: 
   A  B  C
0  6  4  4
1  2  0  3
2  8  3  4
3  7  8  3
4  6  7  8
5  3  3  2
6  5  4  2
7  2  4  7
8  6  1  6
9  1  1  1

In [225]: tuples = [(3,4),(7,8),(1,6)]

In [226]: broadcasting_based(df,tuples)
Out[226]: 
   A  B  C
0  6  4  4
1  2  0  3
3  7  8  3
5  3  3  2
6  5  4  2
7  2  4  7
9  1  1  1

方法#2:覆盖通用数量的列

对于这样的情况,可以将来自不同列的信息折叠成一个表示所有列中唯一性的单个条目。 这可以通过将每一行视为索引元组来实现。 因此,基本上每行将成为一个条目。 类似地,要匹配的元组列表中的每个条目可以减少为1D阵列,每个元组变为一个标量。 最后,我们使用np.in1d查找对应关系,获取有效掩码并删除所需的行数据帧,因此,实现将是 -

def linear_indexing_based(df, tuples):
    idx = np.array(tuples)
    BC_arr = df[['B','C']].values
    shp = np.maximum(BC_arr.max(0)+1,idx.max(0)+1)
    BC_IDs = np.ravel_multi_index(BC_arr.T,shp)
    idx_IDs = np.ravel_multi_index(idx.T,shp)
    return df[~np.in1d(BC_IDs,idx_IDs)]

使用布尔索引可能比对DataFrame.drop的一堆调用更DataFrame.drop 这是因为Pandas不必在每次循环迭代中重新分配内存。

m = pd.Series(False, index=df.index)
for x,y in tuples:
    m |= (df.B == x) & (df.C == y)
df = df[~m]

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM