【问题标题】:pandas subset two dataframes based on multiple columnspandas基于多列子集两个数据帧
【发布时间】:2019-01-25 13:43:08
【问题描述】:

所以,我有两个数据集(我的意思是数据框)如下 数据框 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的常用列。 我们可以看到基于idacctno, dataframe2 在 dataframe1 中。但是dataframe1还有更多 dataframe2 中不常见的记录。

基于一列对两个数据框进行子集是直接的, 但是想知道如何根据两个对两个数据帧进行子集化 列。

所以,结果应该如下所示

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

【问题讨论】:

  • 我相信您在df2 中有错字。我认为第四行的id 应该是2920

标签: python pandas dataframe subset


【解决方案1】:

使用concat 的解决方案,其中我们使用concat df1df2,然后再次df2,因此可以保证删除df2 中的所有行(如果您的DataFrames 是,这可能会导致内存效率低下)非常大):

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 中的某些重复项是故意的 ?
  • 我将其称为我答案的“特征” :) 但这是一个很好的观点,我会澄清
【解决方案2】:

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

【讨论】:

    【解决方案3】:

    设置

    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

    【讨论】:

    • 哇,我喜欢你是如何接受 CoLab 运行时的!
    • @coldspeed 是的,我想我会喜欢的
    猜你喜欢
    • 1970-01-01
    • 2019-05-25
    • 2019-10-22
    • 2019-10-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-14
    • 1970-01-01
    相关资源
    最近更新 更多