webentwicklung-frage-antwort-db.com.de

Wie zählt man eindeutige Datensätze nach zwei Spalten in Pandas?

Ich habe einen Datenrahmen in Pandas:

In [10]: df
Out[10]:
    col_a    col_b  col_c  col_d
0  France    Paris      3      4
1      UK    Londo      4      5
2      US  Chicago      5      6
3      UK  Bristol      3      3
4      US    Paris      8      9
5      US   London     44      4
6      US  Chicago     12      4

Ich muss einzigartige Städte zählen. Ich kann eindeutige Zustände zählen

In [11]: df['col_a'].nunique()
Out[11]: 3

und ich kann versuchen, einzigartige Städte zu zählen

In [12]: df['col_b'].nunique()
Out[12]: 5

aber es ist falsch, weil die USA Paris und Paris in Frankreich unterschiedliche Städte sind. Also mache ich jetzt so:

In [13]: df['col_a_b'] = df['col_a'] + ' - ' + df['col_b']

In [14]: df
Out[14]:
    col_a    col_b  col_c  col_d         col_a_b
0  France    Paris      3      4  France - Paris
1      UK    Londo      4      5      UK - Londo
2      US  Chicago      5      6    US - Chicago
3      UK  Bristol      3      3    UK - Bristol
4      US    Paris      8      9      US - Paris
5      US   London     44      4     US - London
6      US  Chicago     12      4    US - Chicago

In [15]: df['col_a_b'].nunique()
Out[15]: 6

Vielleicht gibt es einen besseren Weg? Ohne eine zusätzliche Spalte anzulegen.

5
GhostKU

Mit ngroups

df.groupby(['col_a', 'col_b']).ngroups
Out[101]: 6

Oder mit set

len(set(Zip(df['col_a'],df['col_b'])))
Out[106]: 6
17
Wen-Ben

Sie können col_a und col_b auswählen, die Duplikate löschen und dann die shape/len des Ergebnisdatenrahmens überprüfen:

df[['col_a', 'col_b']].drop_duplicates().shape[0]
# 6

len(df[['col_a', 'col_b']].drop_duplicates())
# 6

Da groupbyNaNs ignoriert und möglicherweise einen Sortiervorgang unnötig aufruft, wählen Sie die zu verwendende Methode aus, wenn Sie NaNs in den Spalten haben:

Betrachten Sie einen Datenrahmen wie folgt:

df = pd.DataFrame({
    'col_a': [1,2,2,pd.np.nan,1,4],
    'col_b': [2,2,3,pd.np.nan,2,pd.np.nan]
})

print(df)

#   col_a  col_b
#0    1.0    2.0
#1    2.0    2.0
#2    2.0    3.0
#3    NaN    NaN
#4    1.0    2.0
#5    4.0    NaN

Zeitliche Koordinierung :

df = pd.concat([df] * 1000)

%timeit df.groupby(['col_a', 'col_b']).ngroups
# 1000 loops, best of 3: 625 µs per loop

%timeit len(df[['col_a', 'col_b']].drop_duplicates())
# 1000 loops, best of 3: 1.02 ms per loop

%timeit df[['col_a', 'col_b']].drop_duplicates().shape[0]
# 1000 loops, best of 3: 1.01 ms per loop    

%timeit len(set(Zip(df['col_a'],df['col_b'])))
# 10 loops, best of 3: 56 ms per loop

%timeit len(df.groupby(['col_a', 'col_b']))
# 1 loop, best of 3: 260 ms per loop

Ergebnis

df.groupby(['col_a', 'col_b']).ngroups
# 3

len(df[['col_a', 'col_b']].drop_duplicates())
# 5

df[['col_a', 'col_b']].drop_duplicates().shape[0]
# 5

len(set(Zip(df['col_a'],df['col_b'])))
# 2003

len(df.groupby(['col_a', 'col_b']))
# 2003

Also der Unterschied:

Option 1: 

df.groupby(['col_a', 'col_b']).ngroups

ist schnell und schließt Zeilen aus, die NaNs enthalten.

Option 2 & 3:

len(df[['col_a', 'col_b']].drop_duplicates())
df[['col_a', 'col_b']].drop_duplicates().shape[0]

Sie ist relativ schnell und betrachtet NaNs als eindeutigen Wert.

Option 4 & 5:

len(set(Zip(df['col_a'],df['col_b']))) 
len(df.groupby(['col_a', 'col_b'])) 

langsam, und es folgt der Logik, dass numpy.nan == numpy.nan False ist, also werden unterschiedliche (nan, nan) Zeilen als unterschiedlich betrachtet.

5
Psidom
In [105]: len(df.groupby(['col_a', 'col_b']))
Out[105]: 6
4
MaxU

versuchen Sie dies, ich subtrahiere im Grunde die Anzahl der doppelten Gruppen von der Anzahl der Zeilen in df. Dies setzt voraus, dass wir alle Kategorien im df gruppieren

df.shape[0] - df[['col_a','col_b']].duplicated().sum()

774 µs ± 603 ns per loop (mean ± std. dev. of 7 runs, 1000 loops each)

0
Anuj