2016-12-05 4 views
1

Ich habe einen Datenrahmen df_in wie so:Datenrahmen Werte Ersetzen nach der Verwendung von Pandas in Reihen zu entfernen/ersetzen Charakter

import pandas as pd 
import numpy as np 
dic_in = {'A':['aa','bb','cc','dd','ee','ff','gg','uu','xx','yy','zz'], 
     'B':['200','200','AA200','AA040',np.nan,'500',np.nan,'0700','900','UKK','200'], 
     'C':['UNN','400',np.nan,'AA080','AA800','B',np.nan,'400',np.nan,'500','UKK']} 

Mein Ziel ist es Spalte B und C so zu untersuchen, dass:

  • Wenn eines der Elemente das folgende Zeichen 'AA' enthält, muss die Nummer eines solchen Teils der Zeichenfolge entfernt werden, wobei nur der numerische Teil übrig bleibt. (AA123 ---> 123). Wenn Nullen vor dem ersten Nicht-Null-Element vorhanden sind, müssen sie entfernt werden (AA0---> 1234).
  • Wenn die Menge keine Nummer ist, muss sie auf 0.0 (NaN ---> 0.0, UNN ----> 0.0, UKK ---> 0.0 usw.) eingestellt werden.
  • Wenn ein Element hat, bevor führende Nullen, dann müssen sie (070--->700, 00007000--->7000)
  • gelöscht werden, wenn ein Element modifiziert wurde, und ist nicht Null ist, dann muß sie durch 100 multipliziert werden.

Das Endergebnis sollte wie folgt aussehen:

# BEFORE #      # AFTER # 
    A  B  C    A  B  C 
0 aa 200 UNN   0 aa 200 0.0 
1 bb 200 400   1 bb 200 400 
2 cc AA200 NaN   2 cc 20000 0.0 
3 dd AA040 AA080   3 dd 4000 8000 
4 ee NaN AA800   4 ee 0.0 80000 
5 ff 500  B   5 ff 500 0.0 
6 gg NaN NaN   6 gg 0.0 0.0 
7 uu 0700 400   7 uu 700 400 
8 xx 900 NaN   8 xx 900 0.0 
9 yy UKK 500   9 yy 0.0 500 
10 zz 200 UKK   10 zz 200 0.0 

Kennen Sie eine intelligente und effiziente Art und Weise, um dieses Ziel zu erreichen?

Hinweis: alle Zahlen sind in Wirklichkeit Zeichenfolge und sie sollten so bleiben.

Antwort

1

Sie können to_numeric zum Ersetzen nicht numerisch zu NaN verwenden.

Dann extract Zahlen aus Strings, entfernen 0 von links durch lstrip und fügen 00.

Last combine_first mit fillna und Spalten zuweisen:

b = pd.to_numeric(df_in.B, errors='coerce') 
c = pd.to_numeric(df_in.C, errors='coerce') 

b1 = df_in.B.str.extract('(\d+)', expand=False).str.lstrip('0') + '00' 
c1 = df_in.C.str.extract('(\d+)', expand=False).str.lstrip('0') + '00' 

df_in.B = b.combine_first(b1).fillna(0) 
df_in.C = c.combine_first(c1).fillna(0) 
print (df_in) 
    A  B  C 
0 aa 200  0 
1 bb 200 400 
2 cc 20000  0 
3 dd 4000 8000 
4 ee  0 80000 
5 ff 500  0 
6 gg  0  0 
7 uu 700 400 
8 xx 900  0 
9 yy  0 500 
10 zz 200  0 

Ein bisschen modifizierte Lösung letzte fillna von String 0.0 konvertieren alle Werte in Strings (vermeiden Sie einige Strings und einige numerische Werte):

b = pd.to_numeric(df_in.B, errors='coerce') 
c = pd.to_numeric(df_in.C, errors='coerce') 

b1 = df_in.B.str.extract('(\d+)', expand=False).str.lstrip('0') + '00' 
c1 = df_in.C.str.extract('(\d+)', expand=False).str.lstrip('0') + '00' 

df_in.B = b.combine_first(b1) 
df_in.C = c.combine_first(c1) 

df_in = df_in.fillna('0.0').astype(str) 
print (df_in) 
    A  B  C 
0 aa 200.0 0.0 
1 bb 200.0 400.0 
2 cc 20000 0.0 
3 dd 4000 8000 
4 ee 0.0 80000 
5 ff 500.0 0.0 
6 gg 0.0 0.0 
7 uu 700.0 400.0 
8 xx 900.0 0.0 
9 yy 0.0 500.0 
10 zz 200.0 0.0 
1

Angenommen, alle Werte in Ihrem Datenrahmen sind Zeichenfolgen (einschließlich der NaN s, andernfalls können Sie sie in eine geeignete Zeichenfolge mit 0 konvertieren), können Sie die folgende converter Funktion mit applymap für die zwei Spalten verwenden, die Sie konvertieren möchten.

df = pd.DataFrame(dic_in, dtype=str).fillna('NAN') 

converter = lambda x: str(int(x.replace('AA', ''))*100) if 'AA' in x else str(int(x)) if x.isdigit() else '0.0' 

df[['B','C']] = df[['B','C']].applymap(converter) 

Inhalt df:

 A  B  C 
0 aa 200 0.0 
1 bb 200 400 
2 cc 20000 0.0 
3 dd 4000 8000 
4 ee 0.0 80000 
5 ff 500 0.0 
6 gg 0.0 0.0 
7 uu 700 400 
8 xx 900 0.0 
9 yy 0.0 500 
10 zz 200 0.0 
Verwandte Themen