2016-06-12 1 views
1

내가 다음을 수행하고자하는 두 행 3 열 ("ID"정확히 같은 값이있는 경우한 열에서 특정 값을 가진 사람을 중복 행을 제거하지만 유지 (팬더 파이썬)

을 " 기호 "및"날짜 ") 하나의 열 ("메시지 ")에"X "또는"T "가 있으면이 두 행을 모두 제거하십시오. 그러나 두 행의 값이 같은 세 열에 있지만 다른 열의 값이 "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","",""] }) 

처음 두 행이 열 "ID", "기호", 및 "날짜"에 대한 동일한 값을 값을 참고하고, "T : 여기

내 데이터 프레임의 예 "및"X "열에"메시지 ". 이 두 줄을 제거하고 싶습니다.

그러나 "message"열의 "ID", "symbol"및 "date"열의 마지막 두 행의 값은 같지만 "X"또는 "T"와는 다른 공백이 사용됩니다.

나는이 함수를 수백만 행이 포함 된 대형 데이터 세트에 적용하는 데 관심이 있습니다. 조건은 - - 중복 값 및 그룹에서 열 message하지 2 행은 지금까지 내가 시도 내가 당신이 groupbyfilter로 사용할 수 있습니다 생각 내 모든 메모리,

당신을 감사하고 내가 어떤 도움을 주셔서 감사합니다,

+0

2 개 이상인 경우에 대비하여 중복 행을 유지 하시겠습니까? – Stefan

+0

아마도 내 질문에 더 분명하게해야합니다. 내 데이터는 쌍으로 제공됩니다.모든 "X"행에는 "메시지"열을 제외하고 다른 열이 동일한 정확히 "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가 아니라 행이 중복됩니다. – jezrael

+0

맞습니다. 제가 광고 제목의 지시를 따르고있는 것이 맞습니다. 필요한 것을 보자. OP가 2보다 큰 경우 OP가 중복 된 행을 유지하려는 경우 내 대답은 도움이되지 않습니다. – Stefan

+0

concat 함수는이 경우 groupby보다 훨씬 빠르게 실행됩니다 – dleal

0

소비 isin하지가 T 또는 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의 :

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 

값이 TX 인 그룹 만 제거해야하는 경우 각각의 그룹에서 첫 번째 값이 T이고 두 번째 값이 X인지 확인하여 먼저 sort_valuesmessage, 그 다음 filter으로 지정할 수 있습니다. ('T'는 첫 번째와 정렬 때문에 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 
관련 문제