熊猫基于多个列的两个数据框子集

时间:2018-08-19 00:49:55

标签: python pandas dataframe subset

所以,我有两个数据集(我的意思是数据框),如下所示 数据框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

(我们可以将其另存为人口1.csv)

数据框2:

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

(我们可以将其另存为人口2.csv)

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

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

而且,我想得到以下结果

res = df1-df2

基于idacctno的公共列。 我们可以看到,基于idacctno, dataframe2位于dataframe1中。但是dataframe1还有更多 数据框2中不常见的记录。

基于一列对两个数据帧进行子集化是straightforeword, 但是想知道如何基于两个子集来划分两个数据帧 列。

因此,结果应如下所示

ssd, 53, 1901, 238003
ggh, 52, 2221, 222222
eet, 50, 9920, 111111

3 个答案:

答案 0 :(得分: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""")

mask

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

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

Google Colab

GitHub

答案 1 :(得分:3)

使用concat的解决方案,其中我们concat df1df2,然后再df2,因此保证了df2中的所有行被丢弃(如果您的DataFrame很大,这可能会降低内存效率):

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中的重复项,则此答案将忽略您的意愿。

答案 2 :(得分: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