我有一个包含A,B,C
列的数据框。我有一个像[(x1,y1), (x2,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)
也许有一种更简单的方法。
答案 0 :(得分:6)
使用pandas索引
undefined
df.set_index(list('BC')).drop(tuples, errors='ignore').reset_index()
10行,1个元组
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,000行,500个元组
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))]
答案 1 :(得分:4)
方法#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)]
答案 2 :(得分:0)
use boolean indexing可能比对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]