2
votes

Les pandas ne comptent pas correctement les lignes

J'ai donc ce dataframe:

RangeIndex: 57172 entries, 0 to 57171
Data columns (total 8 columns):
filename    57172 non-null object
width       57172 non-null int64
height      57172 non-null int64
class       57172 non-null object
xmin        57172 non-null int64
ymin        57172 non-null int64
xmax        57172 non-null int64
ymax        57172 non-null int64
dtypes: int64(6), object(2)
memory usage: 3.5+ MB

Qui contient dans la colonne appelée "class" ont les valeurs uniques "Panel", "P + SD" et "HS + P + SD" . Je veux compter le nombre de lignes avec ces valeurs, alors j'ai essayé ceci:

56988
0
0

Cela m'a donné cette sortie:

print(len(split_df[split_df["class"].str.contains('Panel')]))
print(len(split_df[split_df["class"].str.contains('HS+P+SD')]))
print(len(split_df[split_df["class"].str.contains('P+SD')]))

Ceci est incorrect comme vous pouvez le voir clairement sur la base de l'extrait de DataFrame fourni ci-dessus, pourquoi tout est-il compté correctement pour Panel mais rien n'est compté pour les deux autres noms de "classe"?

Voici la sortie de split_df.info :

         filename  width  height    class  xmin  ymin  xmax  ymax
0      128782.JPG    640     512    Panel    36   385   119   510
1      128782.JPG    640     512    Panel   124   388   207   510
2      128782.JPG    640     512    Panel   210   390   294   511
3      128782.JPG    640     512    Panel   294   395   380   510
4      128782.JPG    640     512    Panel   379   398   466   511
5      128782.JPG    640     512    Panel   465   402   553   510
6      128782.JPG    640     512     P+SD   552   402   638   510
7      128782.JPG    640     512     P+SD   558   264   638   404
...
...
57170     128782.JPG    640     512     P+SD    36   242   121   383
57171     128782.JPG    640     512  HS+P+SD    36    97   122   242
57172     128782.JPG    640     512     P+SD   214   106   304   250

Je ne peux pas pour la vie de moi comprendre ce qui ne va pas. Toute aide est appréciée.


1 commentaires

J'ai changé le + pour une barre oblique inverse (/). Cela semble avoir résolu mon problème de comptage, pourquoi + interfère-t-il avec cela?


3 Réponses :


6
votes

pd.Series. str.contains a regex = True par défaut. Puisque + est un caractère spécial dans l'expression régulière, utilisez regex = False , re.escape ou \ en échappant:

L = ['Panel', 'HS+P+SD', 'P+SD']
counts = df.loc[df['class'].isin(L), 'class'].value_counts()

Je veux compter le nombre de lignes avec ces valeurs

S'il s'agit de votre problème principal et que vous ne voulez pas qu'un compte 'P + SD' inclue 'HS + P + SD' , n'utilisez pas str.contains . Vérifiez plutôt l'égalité et utilisez value_counts code> sur les valeurs que vous souhaitez compter:

import re
s = pd.Series(['HS+P+SD', 'AB+CD+EF'])

s.str.contains('HS+P+SD').sum()               # 0
s.str.contains('HS+P+SD', regex=False).sum()  # 1
s.str.contains(re.escape('HS+P+SD')).sum()    # 1
s.str.contains('HS\+P\+SD').sum()             # 1

Ou pour tous les comptes, utilisez simplement df ['class' ] .value_counts () .


2 commentaires

Sinon, s.value_counts () devrait s'en occuper pour vous.


@piRSquared, j'y ai pensé, mais les données d'OP ont P + SD et HS + P + SD , donc ils veulent peut-être rechercher le premier pour inclure le second.



1
votes

Essayez :

print(len(split_df[split_df["class"].str == 'HS+P+SD']))


1 commentaires

Cela fonctionnait aussi bien, regex voyait fondamentalement + comme un signe spécial. Merci pour l'aide :)



1
votes

Une boucle for simple avec in fonctionnera également

df=pd.concat([df]*100)
%timeit df['class'].str.contains('HS+P+SD', regex=False).sum()
1000 loops, best of 3: 410 µs per loop
%timeit sum(['HS+P+SD' in x for x in df['class']])
10000 loops, best of 3: 123 µs per loop

À propos du timing (si vous voulez vérifier ceci lien )

sum(['HS+P+SD' in x for x in df['class']])


0 commentaires