복붙노트

[SQL] SQL을 뺀 팬더 아날로그는 / 여러 열을 사용하여 연산자를 EXCEPT

SQL

SQL을 뺀 팬더 아날로그는 / 여러 열을 사용하여 연산자를 EXCEPT

나는 SQL의 MINUS (AKA 제외) 운영자에게 빠르고 관용적 아날로그를 찾고 있어요.

여기에 내가 무슨 뜻입니다 - 다음과 같이 두 팬더 DataFrames을 제공 :

In [77]: d1
Out[77]:
   a  b  c
0  0  0  1
1  0  1  2
2  1  0  3
3  1  1  4
4  0  0  5
5  1  1  6
6  2  2  7

In [78]: d2
Out[78]:
   a  b   c
0  1  1  10
1  0  0  11
2  1  1  12

방법은 다음과 같은 결과를 얻기 위해 열만 계정에 "A"와 "B"를 복용 D1 빼기 (D2)의 결과를 찾을 수 :

In [62]: res
Out[62]:
   a  b  c
1  0  1  2
2  1  0  3
6  2  2  7

MVCE :

d1 = pd.DataFrame({
    'a': [0, 0, 1, 1, 0, 1, 2], 
    'b': [0, 1, 0, 1, 0, 1, 2], 
    'c': [1, 2, 3, 4, 5, 6, 7]
})

d2 = pd.DataFrame({
    'a': [1, 0, 1], 
    'b': [1, 0, 1], 
    'c': [10, 11, 12]
})

나는 무엇을 시도했다 :

In [65]: tmp1 = d1.reset_index().set_index(["a", "b"])

In [66]: idx = tmp1.index.difference(d2.set_index(["a","b"]).index)

In [67]: res = d1.loc[tmp1.loc[idx, "index"]]

In [68]: res
Out[68]:
   a  b  c
1  0  1  2
2  1  0  3
6  2  2  7

그것은 나에게 정확한 결과를 제공하지만, 나는 그것을 달성하기 위해 더 관용적하고 좋네요 / 청소기 방법이 있어야한다는 느낌이 듭니다.

PS DataFrame.isin () 메서드는 잘못된 결과 집합을이 경우하지의 도움을 생산하는 것이다하므로

해결법

  1. ==============================

    1.우리는 여기 drop_duplicates와 pandas.concat를 사용 킵 = False로 모든 중복을 드롭 그것을 인수를 전달할 수 있습니다 :

    우리는 여기 drop_duplicates와 pandas.concat를 사용 킵 = False로 모든 중복을 드롭 그것을 인수를 전달할 수 있습니다 :

    pd.concat([d1, d2]).drop_duplicates(['a', 'b'], keep=False)
    
       a  b  c
    1  0  1  2
    2  1  0  3
    6  2  2  7
    

    ON에서 코멘트 후 편집

    당신이 DF2 독특한 행이 고려 ARNT 있는지 확인하려면, 우리는 DF를 복제 할 수 있습니다 :

    pd.concat([d1, pd.concat([d2]*2)]).drop_duplicates(['a', 'b'], keep=False)
    
       a  b  c
    1  0  1  2
    2  1  0  3
    6  2  2  7
    
  2. ==============================

    2.여기 Excel과 같은 약간의 생각입니다 :

    여기 Excel과 같은 약간의 생각입니다 :

    d1[~d1[['a','b']].astype(str).sum(axis=1).isin(d2[['a','b']].astype(str).sum(axis=1))]
    
       a  b  c
    1  0  1  2
    2  1  0  3
    6  2  2  7
    
  3. ==============================

    3.병합 및 표시와 한 가지 가능한 솔루션은 진정한 =

    병합 및 표시와 한 가지 가능한 솔루션은 진정한 =

    df = (d1.reset_index()
            .merge(d2, on=['a','b'], indicator=True, how='outer', suffixes=('','_'))
            .query('_merge == "left_only"')
            .set_index('index')
            .rename_axis(None)
            .reindex(d1.columns, axis=1))
    print (df)
       a  b  c
    1  0  1  2
    2  1  0  3
    6  2  2  7
    

    ISIN과 해결 방법 :

    df = d1[~d1.set_index(["a", "b"]).index.isin(d2.set_index(["a","b"]).index)]
    print (df)
       a  b  c
    1  0  1  2
    2  1  0  3
    6  2  2  7
    
  4. ==============================

    4.

    In [100]: df1 = pd.concat([d1] * 10**5, ignore_index=True)
    
    In [101]: df2 = pd.concat([d2] * 10**5, ignore_index=True)
    
    In [102]: df1.shape
    Out[102]: (700000, 3)
    
    In [103]: df2.shape
    Out[103]: (300000, 3)
    
    In [10]: %%timeit
        ...: res = pd.concat([d1, pd.concat([d2]*2)]).drop_duplicates(['a', 'b'], keep=False)
        ...:
        ...:
    2.59 ms ± 129 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
    
    In [11]: %%timeit
        ...: res = df1[~df1.set_index(["a", "b"]).index.isin(df2.set_index(["a","b"]).index)]
        ...:
        ...:
    484 ms ± 18.6 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
    
    In [12]: %%timeit
        ...: tmp1 = df1.reset_index().set_index(["a", "b"])
        ...: idx = tmp1.index.difference(df2.set_index(["a","b"]).index)
        ...: res = df1.loc[tmp1.loc[idx, "index"]]
        ...:
        ...:
    1.04 s ± 20.7 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
    
    In [106]: %%timeit
         ...: res =  (df1.reset_index()
         ...:         .merge(df2, on=['a','b'], indicator=True, how='outer', suffixes=('','_'))
         ...:         .query('_merge == "left_only"')
         ...:         .set_index('index')
         ...:         .rename_axis(None)
         ...:         .reindex(df1.columns, axis=1))
         ...:
         ...:
    ---------------------------------------------------------------------------
    MemoryError                               Traceback (most recent call last)
    
    In [13]: %%timeit
        ...: res = df1[~df1[['a','b']].astype(str).sum(axis=1).isin(df2[['a','b']].astype(str).sum(axis=1))]
        ...:
        ...:
    2.05 s ± 65.2 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
    
  5. ==============================

    5.나는 당신의 생각을했는데, 비슷한 질문을했다

    나는 당신의 생각을했는데, 비슷한 질문을했다

    (
    In [65]: tmp1 = d1.reset_index().set_index(["a", "b"])
    
    In [66]: idx = tmp1.index.difference(d2.set_index(["a","b"]).index)
    
    In [67]: res = d1.loc[tmp1.loc[idx, "index"]]
    
    )
    

    테스트와 그것을 작동합니다.

    그러나, 나는 같은 구조를 가지고 내 sqlite가, 견인 데이터베이스 방식을 사용, 즉 그 테이블과 테이블 '열이 같은 의미, 그리고 몇 가지 실수를 발생,이 두 DF가 같은 shap이없는 것 같다 보여줍니다 .

    u는 나에게 손을주고 행복 R 및 더 자세한 정보를 원한다면, 우리는 더 대화 덕분에 많이있을 수 있습니다

  6. from https://stackoverflow.com/questions/56235226/pandas-analogue-to-sql-minus-except-operator-using-multiple-columns by cc-by-sa and MIT license