2016-06-12 4 views
1

内の特定の値を持つものを保つ:私は次の操作を実行したい重複行を削除するが、1つのカラム(パンダパイソン)

2つの行が3列(「ID」、でまったく同じ値を持っている場合」 1つの列(「メッセージ」)に「X」または「T」のいずれかを持ち、これらの行を両方とも削除します。ただし、2つの行が同じ3つの列で同じ値を持ち、もう1つの列で「X」または「T」と異なる値を持つ場合は、そのまま残ります。ここ

は私のデータ・フレームの例である:

df = pd.DataFrame({"ID":["AA-1", "AA-1", "C-0" ,"BB-2", "BB-2"], "symbol":["A","A","C","B","B"], "date":["06/24/2014","06/24/2014","06/20/2013","06/25/2014","06/25/2015"], "message": ["T","X","T","",""] }) 

なお、第1の2つの行が同じ値の列の値が「ID」、「シンボル」、及び「日付」を有し、「Tこと"と" X "は"メッセージ "の列に表示されます。私はこれらの2つの行を削除したいと思います。

しかし、最後の2つの行は、「ID」、「記号」、および「日付」の列で同じ値を持ちますが、「メッセージ」列の空白(「X」または「T」とは異なります)

私は数百万行の大きなデータセットにこの関数を適用することに興味があります。これまでのところ、私が試してみましたが、すべて私の記憶を消費し、私はあなたがfiltergroupbyを使用することができると思う

はあなたに感謝し、私は任意の助けに感謝、

+0

2つ以上の場合に備えて重複した行を保存したいですか? – Stefan

+0

私はおそらく私の質問でより明確にする必要があります。私のデータはペアになっています。すべての「X」行には、「メッセージ」列を除いて他の列が等しい、正確に1つの「T」行が存在する(または少なくともあるはずである)。この場合、少なくともデータが正しく収集されていれば、一致する観測のペアのみが存在する必要があります。 – dleal

答えて

0

これはあなたのために働くかもしれない:

vals = ['X', 'T'] 
pd.concat([df[~df.message.isin(vals)], df[df.message.isin(vals)].loc[~df.duplicated(subset=['ID', 'date', 'symbol'], keep=False), :]]) 

    ID  date message symbol 
3 BB-2 06/25/2014    B 
4 BB-2 06/25/2015    B 
2 C-0 06/20/2013  T  C 

それは合理的に高速です:

%%timeit 
pd.concat([df[~df.message.isin(['X', 'T'])], df[df.message.isin(['X', 'T'])].loc[~df.duplicated(subset=['ID', 'date', 'symbol'], keep=False), :]]) 
100 loops, best of 3: 1.99 ms per loop 

%%timeit 
df.groupby(['ID','date','symbol']).filter(lambda x: ~x.message.isin(['T','X']).all()) 
100 loops, best of 3: 2.71 ms per loop 

代替を与えていました索引付けエラー。

+0

'2つの行がまったく同じ値を持っている場合、問題があります。' - ソリューションフィルタは長さ2だけでなく、すべての行を複製します。 – jezrael

+0

それは私が見出しの指示に従った直後です。何が必要なのか見てみましょう。 OPが2より大きい場合、OPが重複した行を保持したい場合、私の答えは役に立たないでしょう。 – Stefan

+0

concat関数は、この場合groupbyよりもはるかに高速に実行されます – dleal

0

- 条件がある - グループ内の重複した値と列messageでない2isinTまたはX値いない:

import pandas as pd 

df = pd.DataFrame({"ID":["AA-1", "AA-1", "C-0" ,"BB-2", "BB-2"], 
        "symbol":["A","A","C","B","B"], 
        "date":["06/24/2014","06/24/2014","06/20/2013","06/25/2015","06/25/2015"], 
        "message": ["T","X","T","",""] }) 
print (df) 
    ID  date message symbol 
0 AA-1 06/24/2014  T  A 
1 AA-1 06/24/2014  X  A 
2 C-0 06/20/2013  T  C 
3 BB-2 06/25/2015    B 
4 BB-2 06/25/2015    B 

df1 = df.groupby(['ID','date','symbol']).filter(lambda x: ~((len(x) == 2) & 
                  (x.message.isin(['T','X']).all()))) 
print (df1) 
    ID  date message symbol 
2 C-0 06/20/2013  T  C 
3 BB-2 06/25/2015    B 
4 BB-2 06/25/2015    B 

Filtration in docs

commentによってEDIT:

import pandas as pd 

df = pd.DataFrame({"ID":["AA-1", "AA-1", "C-0", "C-0","BB-2", "BB-2"], 
        "symbol":["A","A","C","C", "B","B"], 
        "date":["06/24/2014","06/24/2014","06/20/2013","06/20/2013","06/25/2015","06/25/2015"], 
        "message": ["T","X","X","X","",""] }) 
print (df) 
    ID  date message symbol 
0 AA-1 06/24/2014  T  A 
1 AA-1 06/24/2014  X  A 
2 C-0 06/20/2013  X  C 
3 C-0 06/20/2013  X  C 
4 BB-2 06/25/2015    B 
5 BB-2 06/25/2015    B 

に、各グループにXまたはTで値を削除が必要な場合 - それはあまりにも重XまたはダブルTを取り除く意味し、各グループの各lenは常に2です:

df1 = df.groupby(['ID','date','symbol']).filter(lambda x: ~x.message.isin(['T','X']).all()) 
print (df1) 
    ID  date message symbol 
4 BB-2 06/25/2015    B 
5 BB-2 06/25/2015    B 

値がTおよびXのグループのみを削除する必要がある場合は、最初にをmessageとし、次にfilterとすると、最初の値がTで、2番目がXであるかどうかを確認することができます。 ( 'T' は、第1であると仕分けのでXは、秒):

df2 = df.sort_values('message') 
     .groupby(['ID','date','symbol'], sort=False) 
     .filter(lambda x: ((x.message.iloc[0] != 'T') | (x.message.iloc[1] != 'X'))) 
print (df2) 
    ID  date message symbol 
4 BB-2 06/25/2015    B 
5 BB-2 06/25/2015    B 
2 C-0 06/20/2013  X  C 
3 C-0 06/20/2013  X  C 
関連する問題