2016-07-28 14 views
9

Mam duży plik danych i muszę usunąć wiersze zakończone pewnymi literami.Python: Jak usunąć wiersze kończące się niektórymi znakami?

Oto przykład pliku używam:

User Name  DN 
MB212DA  CN=MB212DA,CN=Users,DC=prod,DC=trovp,DC=net 
MB423DA  CN=MB423DA,OU=Generic Mailbox,DC=prod,DC=trovp,DC=net 
MB424PL  CN=MB424PL,CN=Users,DC=prod,DC=trovp,DC=net 
MBDA423  CN=MBDA423,OU=DNA,DC=prod,DC=trovp,DC=net 
MB2ADA4  CN=MB2ADA4,OU=DNA,DC=prod,DC=trovp,DC=netenter code here 

kod używam:

from pandas import DataFrame, read_csv 
import pandas as pd 
f = pd.read_csv('test1.csv', sep=',',encoding='latin1') 
df = f.loc[~(~pd.isnull(f['User Name']) & f['UserName'].str.contains("DA|PL",))] 

Jak używać składni wyrażeń regularnych do usunięcia słów, które kończą się " DA "i" PL ", ale upewnij się, że nie usuwam pozostałych wierszy, ponieważ zawierają one" DA "lub" PL "wewnątrz nich?

Należy usunąć wiersze i I skończyć z pliku jak poniżej:

User Name  DN 
MBDA423  CN=MBDA423,OU=DNA,DC=prod,DC=trovp,DC=net 
MB2ADA4  CN=MB2ADA4,OU=DNA,DC=prod,DC=trovp,DC=net 

Pierwsze 3 wiersze są usuwane, ponieważ zakończył się w DA i PL.

Odpowiedz

7

Można użyć tego wyrażenia

df = df[~df['User Name'].str.contains('(?:DA|PL)$')] 

Zwróci wszystkie wiersze, które nie kończą się ani na DA, ani na PL.

The ?: jest tak, że nawiasy nic nie przechwycą. W przeciwnym razie, można zobaczyć pandy powrocie następujące (nieszkodliwe) UWAGA:

UserWarning: This pattern has match groups. To actually get the groups, use str.extract. 

Alternatywnie, przy użyciu endswith() i bez wyrażeń regularnych, ta sama filtracja można osiągnąć za pomocą następującego wyrażenia:

df = df[~df['User Name'].str.endswith(('DA', 'PL'))] 

Zgodnie z oczekiwaniami wersja bez regularnego wyrażenia będzie szybsza. Prosty test, składający się z big_df, który składa się z 10001 egzemplarzy oryginalnego df:

# Create a larger DF to get better timing results 
big_df = df.copy() 

for i in range(10000): 
    big_df = big_df.append(df) 

print(big_df.shape) 

>> (50005, 2) 

# Without regular expressions 
%%timeit 
big_df[~big_df['User Name'].str.endswith(('DA', 'PL'))] 

>> 10 loops, best of 3: 22.3 ms per loop 

# With regular expressions 
%%timeit 
big_df[~big_df['User Name'].str.contains('(?:DA|PL)$')] 

>> 10 loops, best of 3: 61.8 ms per loop 
+0

Nie endswith akceptują regex? Podejrzewam, że używa jednego pod maską. –

+0

Też tak pomyślałem, nawet doktorzy twierdzą, że pierwszy argument jest wzorcem, ale nie mogłem go rozpoznać w regex. –

+1

@AndyHayden widocznie to bierze krotkę. –

0

Zamiast regular expressions można użyć metody endswith(), aby sprawdzić, czy ciąg kończy się określonym wzorcem.

tj .:

for row in rows: 
    if row.endswith('DA') or row.endswith('PL'): 
     #doSomething 

Należy utworzyć inny df używając przefiltrowanych danych, a następnie użyć pd.to_csv() zaoszczędzić czystą wersję pliku.

2

Można użyć logiczną maskę czym sprawdzić, czy dwa ostatnie znaki User_Name są w nie (~) w zestawie z dwoma zakończeniami Charakter:

>>> df[~df.User_Name.str[-2:].isin(['DA', 'PA'])] 
    User_Name             DN 
2 MB424PL CN=MB424PL, CN=Users, DC=prod, DC=trovp, DC=net 
3 MBDA423  CN=MBDA423, OU=DNA, DC=prod, DC=trovp, DC=net 
4 MB2ADA4 CN=MB2ADA4, OU=DNA, DC=prod, DC=trovp, DC=nete... 
Powiązane problemy