web-dev-qa-db-fra.com

Python: Pandas filtre les données de chaîne en fonction de sa longueur de chaîne

J'aime filtrer les données dont la longueur de chaîne n'est pas égale à 10.

Si j'essaie de filtrer toute ligne dont la longueur de chaîne de la colonne A ou B n'est pas égale à 10, j'ai essayé ceci.

df=pd.read_csv('filex.csv')
df.A=df.A.apply(lambda x: x if len(x)== 10 else np.nan)
df.B=df.B.apply(lambda x: x if len(x)== 10 else np.nan)
df=df.dropna(subset=['A','B'], how='any')

Cela fonctionne lentement, mais fonctionne.

Cependant, cela produit parfois une erreur lorsque les données dans A ne sont pas une chaîne mais un nombre (interprété comme un nombre lorsque read_csv lit le fichier d'entrée).

  File "<stdin>", line 1, in <lambda>
TypeError: object of type 'float' has no len()

Je pense qu'il devrait y avoir un code plus efficace et plus élégant à la place de cela.


Sur la base des réponses et des commentaires ci-dessous, la solution la plus simple que j'ai trouvée est:

df=df[df.A.apply(lambda x: len(str(x))==10]
df=df[df.B.apply(lambda x: len(str(x))==10]

ou

df=df[(df.A.apply(lambda x: len(str(x))==10) & (df.B.apply(lambda x: len(str(x))==10)]

ou

df=df[(df.A.astype(str).str.len()==10) & (df.B.astype(str).str.len()==10)]
42
notilas
import pandas as pd

df = pd.read_csv('filex.csv')
df['A'] = df['A'].astype('str')
df['B'] = df['B'].astype('str')
mask = (df['A'].str.len() == 10) & (df['B'].str.len() == 10)
df = df.loc[mask]
print(df)

Appliqué à filex.csv:

A,B
123,abc
1234,abcd
1234567890,abcdefghij

le code ci-dessus s'imprime

            A           B
2  1234567890  abcdefghij
72
unutbu

Une façon plus pythonique de filtrer les lignes en fonction des conditions données des autres colonnes et de leurs valeurs:

En supposant un df de:

data={"names":["Alice","Zac","Anna","O"],"cars":["Civic","BMW","Mitsubishi","Benz"],
     "age":["1","4","2","0"]}

df=pd.DataFrame(data)
df:
  age        cars  names
0   1       Civic  Alice
1   4         BMW    Zac
2   2  Mitsubishi   Anna
3   0        Benz      O

Ensuite:

df[
df['names'].apply(lambda x: len(x)>1) &
df['cars'].apply(lambda x: "i" in x) &
df['age'].apply(lambda x: int(x)<2)
  ]

Nous aurons :

  age   cars  names
0   1  Civic  Alice

Dans les conditions ci-dessus, nous examinons d'abord la longueur des chaînes, puis nous vérifions si une lettre ("i") existe ou non dans les chaînes, enfin, nous vérifions la valeur des entiers dans la première colonne.

12
Mahdi Ghelichi

Si vous avez des nombres dans les lignes, ils se convertiront en flottants.

Convertissez toutes les lignes en chaînes après l'importation à partir de cvs. Pour de meilleures performances, divisez ce lambdas en plusieurs threads.

1
przemo_li