2016-05-05 11 views
0

fallen lassen Ich bin neu bei Python und Pandas, also bitte mit mir ertragen. Ich habe ein ziemlich einfaches Problem zu lösen, aber ich scheine es nicht richtig zu verstehen. Ich habe eine CSV-Datei, die ich mit einem Pandas-Datenrahmen bearbeiten möchte. Die Daten zeigen Flüsse von Heimat- zu Arbeitsorten und die entsprechenden IDs der Orte sowie Koordinaten in lat/lon und einen Wert für jeden Fluss.Wie man Zeilen von Pandas Datenrahmen mit dem gleichen Wert basierend auf Bedingung in verschiedenen Spalte

id_home,name_home,lat_home,lon_home,id_work,work,lat_work,lon_work,value 
1001,"Flensburg",54.78879007,9.4459971,1002,"Kiel",54.34189351,10.13048288,695 
1001,"Flensburg",54.78879007,9.4459971,1003,"Lübeck, Hansestadt",53.88132436,10.72749774,106 
1001,"Flensburg",54.78879007,9.4459971,1004,"Neumünster, Stadt",54.07797524,9.974475148,124 
1001,"Flensburg",54.78879007,9.4459971,1051,"Dithmarschen",54.12904835,9.120139194,39 
1001,"Flensburg",54.78879007,9.4459971,10,"Schleswig-Holstein",54.212,9.959,7618 
1001,"Flensburg",54.78879007,9.4459971,1,"Schleswig-Holstein",54.20896049,9.957114419,7618 
1001,"Flensburg",54.78879007,9.4459971,2000,"Hamburg, Freie und Hansestadt",53.57071859,9.943770215,567 
1001,"Flensburg",54.78879007,9.4459971,20,"Hamburg",53.575,9.941,567 
1001,"Flensburg",54.78879007,9.4459971,2,"Hamburg",53.57071859,9.943770215,567 
1003,"Lübeck",53.88132436,10.72749774,100,"Saarland",49.379,6.979,25 
1003,"Lübeck",53.88132436,10.72749774,10,"Saarland",54.212,9.959,25 
1003,"Lübeck",53.88132436,10.72749774,11000,"Berlin, Stadt",52.50395948,13.39337765,274 
1003,"Lübeck",53.88132436,10.72749774,110,"Berlin",52.507,13.405,274 
1003,"Lübeck",53.88132436,10.72749774,11,"Berlin",52.50395948,13.39337765,274 

Ich möchte alle benachbarten doppelten Zeilen mit dem gleichen Wert löschen und nur die letzte Zeile zu halten, wo id_work entweder eines einstelligen oder zweistelligen Bereich. Alle anderen Zeilen sollten gelöscht werden. Wie kann ich das erreichen? Was ich im Wesentlichen brauche, ist die folgende Ausgabe:

id_home,name_home,lat_home,lon_home,id_work,work,lat_work,lon_work,value 
1001,"Flensburg",54.78879007,9.4459971,1002,"Kiel",54.34189351,10.13048288,695 
1001,"Flensburg",54.78879007,9.4459971,1003,"Lübeck, Hansestadt",53.88132436,10.72749774,106 
1001,"Flensburg",54.78879007,9.4459971,1004,"Neumünster, Stadt",54.07797524,9.974475148,124 
1001,"Flensburg",54.78879007,9.4459971,1051,"Dithmarschen",54.12904835,9.120139194,39 
1001,"Flensburg",54.78879007,9.4459971,1,"Schleswig-Holstein",54.20896049,9.957114419,7618 
1001,"Flensburg",54.78879007,9.4459971,2,"Hamburg",53.57071859,9.943770215,567 
1003,"Lübeck",53.88132436,10.72749774,10,"Saarland",54.212,9.959,25 
1003,"Lübeck",53.88132436,10.72749774,11,"Berlin",52.50395948,13.39337765,274 

Super dankbar für jede Hilfe!

+0

Sind die Duplikate immer benachbart? Möchtest du immer den letzten behalten? –

+0

Ja, sie sind immer benachbart. In einigen Fällen gibt es bis zu vier Duplikate mit 4,3,2- und 1-stelligen IDs. Ich möchte nur die letzte (d. H. 1-stellige) Zeile behalten. – Yoya01

+0

basierend auf Ihren überarbeiteten Beispieldaten 'df.drop_duplicates ('value', keep = 'last') 'sollte funktionieren – EdChum

Antwort

0

drop_duplicates hat einen keep param, setzen Sie ihn auf last:

In [188]: 
df.drop_duplicates(subset=['value'], keep='last') 

Out[188]: 
    id name value 
0 345 name1 456 
1 12 name2 220 
5 2 name6 567 

Eigentlich denke ich, die folgende ist, was Sie wollen:

In [197]: 
df.drop(df.index[(df['value'].isin(df.loc[df['value'].duplicated(), 'value'].unique())) & (df['id'].astype(str).str.len() != 1)]) 

Out[197]: 
    id name value 
0 345 name1 456 
1 12 name2 220 
5 2 name6 567 

Hier wir die Zeilenbeschriftungen löschen, die doppelte Werte haben und wo die "ID" -Länge nicht 1 ist, ein Zusammenbruch:

In [198]: 
df['value'].duplicated() 

Out[198]: 
0 False 
1 False 
2 False 
3  True 
4  True 
5  True 
Name: value, dtype: bool 

In [199]: 
df.loc[df['value'].duplicated(), 'value'] 

Out[199]: 
3 567 
4 567 
5 567 
Name: value, dtype: int64 

In [200]: 
df['value'].isin(df.loc[df['value'].duplicated(), 'value'].unique()) 

Out[200]: 
0 False 
1 False 
2  True 
3  True 
4  True 
5  True 
Name: value, dtype: bool 

In [201]: 

(df['value'].isin(df.loc[df['value'].duplicated(), 'value'].unique())) & (df['id'].astype(str).str.len() != 1) 

Out[201]: 
0 False 
1 False 
2  True 
3  True 
4  True 
5 False 
dtype: bool 

In [202]: 
df.index[(df['value'].isin(df.loc[df['value'].duplicated(), 'value'].unique())) & (df['id'].astype(str).str.len() != 1)] 

Out[202]: 
Int64Index([2, 3, 4], dtype='int64') 

Also verwendet das obige duplicated um die duplizierten Werte zurückzugeben, unique um nur die eindeutigen duplizierten Werte zurückzugeben, isin um die Mitgliedschaft zu testen wir die Spalte 'id' auf str setzen damit wir die Länge mit str.len testen und die boole'sche Maske benutzen können die Indexbeschriftungen.

+0

Danke! Dies scheint jedoch alle Duplikate im gesamten Datensatz zu löschen. Ich möchte nur die Duplikate löschen, die nebeneinander liegen, dh wenn es mindestens zwei Duplikate nebeneinander gibt, lösche alles außer denen, bei denen id.len 1. – Yoya01

+1

Du solltest das in deiner Frage so angeben Angelegenheiten – EdChum

+0

Ja, sorry dafür! – Yoya01

0

Lassen Sie uns dies auf den Fall vereinfachen, wo Sie ein einzelnes Array haben:

arr = np.array([1, 1, 1, 2, 0, 0, 1, 1, 2, 0, 0, 0, 0, 2, 1, 0, 0, 1, 1, 1]) 

die wir nun eine Reihe von bools erzeugen, die uns die Orte zeigt, wo die Werte ändern:

arr[1:] != arr[:-1] 

Das sagt uns welche Werte wir behalten wollen - die Werte, die sich von den nächsten unterscheiden. Aber es läßt den letzten Wert aus, die immer enthalten sein sollten, so:

mask = np.hstack((arr[1:] != arr[:-1], True)) 

Nun arr[mask] gibt uns:

array([1, 2, 0, 1, 2, 0, 2, 1, 0, 1]) 

Und falls Sie nicht glauben, das letzte Vorkommen jedes Element numerisch war ausgewählt, können Sie mask.nonzero() überprüfen, um die Indizes zu erhalten:

array([ 2, 3, 5, 7, 8, 12, 13, 14, 16, 19]) 

Nun, da Sie wissen, wie die Maske für eine einzelne Spalte zu erzeugen, können Sie einfach es auf Ihre gesamter Datenrahmen als df[mask].

+0

Das ist wirklich, was ich suche! Kann ich trotzdem nicht herausfinden, wie ich es auf meinen gesamten Datenrahmen anwenden kann? Kannst du mir vielleicht noch einen Hinweis auf den nächsten Schritt geben? – Yoya01

+0

'df [mask]' wendet es auf den gesamten Datenrahmen an. –

Verwandte Themen