基于多列条件,将pandas数据框进行子集筛选

3

所以,我有两个数据集(我是指数据帧)如下: 数据帧1:

name, age, id, acctno
abc, 23, 1001, 238238
dhd, 22, 2001, 299299
ddg, 30, 2920, 101010
ssd, 53, 1901, 238003
ggh, 52, 2221, 222222
eet, 50, 9920, 111111

我们可以将其保存为population1.csv。

数据框2:

name, age, id, acctno
abc, 11, 1001, 238238
def, 55, 2001, 299299
xxy, 90, 2020, 101010

我们可以将其保存为population2.csv。

因此,我们可以按照以下方式读取数据:

df1 = pd.read_csv('population1.csv')
df2 = pd.read_csv('population2.csv')

并且,我希望得到以下结果。
res = df1-df2

基于idacctno的公共列,我们可以看到dataframe2dataframe1中。但是dataframe1有一些不同于dataframe2的记录。
基于一列对两个数据框进行子集操作很简单,但是想知道如何基于两列对两个数据框进行子集操作。
因此,结果应该如下所示。
ssd, 53, 1901, 238003
ggh, 52, 2221, 222222
eet, 50, 9920, 111111

我认为你在 df2 中打错了字。我认为第四行的 id 应该是 2920 - piRSquared
3个回答

4

设置

def rpd(text='', sep='\s{1,}', *args, **kwargs):
  kw = dict(engine='python', sep=sep)
  return pd.read_csv(pd.io.common.StringIO(text), *args, **kw, **kwargs)

df1 = rpd(sep=',\s*', text="""\
name, age, id, acctno
abc, 23, 1001, 238238
dhd, 22, 2001, 299299
ddg, 30, 2920, 101010
ssd, 53, 1901, 238003
ggh, 52, 2221, 222222
eet, 50, 9920, 111111""")

df2 = rpd(sep=',\s*', text="""\
name, age, id, acctno
abc, 11, 1001, 238238
def, 55, 2001, 299299
xxy, 90, 2020, 101010""")

口罩

df2_tups = [*zip(df2.id, df2.acctno)]
mask = [t not in df2_tups for t in zip(df1.id, df1.acctno)]
df1[mask]

  name  age    id  acctno
2  ddg   30  2920  101010
3  ssd   53  1901  238003
4  ggh   52  2221  222222
5  eet   50  9920  111111

合并

merge 函数/方法有一个 indicator 参数,如果设置为 True,则会添加一列,告诉您合并标识符位于哪个数据源中。在您的情况下,您想获取仅剩下的部分。

df1.merge(
    df2[['id', 'acctno']], how='left', indicator=True
).query('_merge == "left_only"').drop('_merge', 1)

  name  age    id  acctno
2  ddg   30  2920  101010
3  ssd   53  1901  238003
4  ggh   52  2221  222222
5  eet   50  9920  111111

谷歌协作平台

GitHub


2
哇,我喜欢你如何拥抱CoLab运行时! - cs95
@coldspeed,是的,我想我会喜欢它。 - piRSquared

3
使用concat解决方案,其中我们concat df1、df2,然后再次concat df2,以保证从df2中删除所有行(如果您的数据帧非常大,则可能存在内存效率问题):
pd.concat([df1, df2, df2]).drop_duplicates(['id', 'acctno'], keep=False)

  name  age    id  acctno
2  ddg   30  2920  101010
3  ssd   53  1901  238003
4  ggh   52  2221  222222
5  eet   50  9920  111111

如果您在df1中有重复项需要保留,本答案将忽略您的意愿。

聪明!但是如果df1中的一些重复是有意的呢? - piRSquared
我会把它称为我的回答的“特点” :) 但这是一个很好的观点,我会澄清。 - user3483203

3

isinapply tuple的结合使用

df1.loc[~df1[['id', 'acctno']].apply(tuple,1).isin(df2[['id', 'acctno']].apply(tuple,1))]
Out[215]: 
  name  age    id  acctno
2  ddg   30  2920  101010
3  ssd   53  1901  238003
4  ggh   52  2221  222222
5  eet   50  9920  111111

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接