2015-06-20 22 views
5

Für pandas suche ich nach einer Möglichkeit, bedingte Werte für jede Zeile in Spalte B basierend auf Teilstrings für entsprechende schreiben Zeilen in Spalte A.Pandas: Wenn Zeile in Spalte A "x" enthält, schreibe "y" in Zeile B

Wenn Zelle A"BULL" enthält, schreiben Sie an B. Oder wenn Zelle in A"BEAR" enthält, schreiben Sie "Short" zu B.

gewünschte Ausgabe:

A     B 
"BULL APPLE X5" "Long" 
"BEAR APPLE X5" "Short" 
"BULL APPLE X5" "Long" 

B ist zunächst leer: df = pd.DataFrame([['BULL APPLE X5',''],['BEAR APPLE X5',''],['BULL APPLE X5','']],columns=['A','B'])

+0

Dies ist ein sehr gute Frage. Die gewünschte Spalte B ist Binary, wenn Sie B basierend auf der String-Suche zuweisen müssen. – user3341078

Antwort

6

Ihr Code würde Fehler, wie Sie fälschlicherweise den Datenrahmen zu schaffen, nur eine einzige Spalte erstellen A dann B hinzufügen, basierend auf A:

import pandas as pd 
df = pd.DataFrame(["BULL","BEAR","BULL"], columns=['A']) 
df["B"] = ["Long" if ele == "BULL" else "Short" for ele in df["A"]] 

print(df) 

    A  B 
0 BULL Long 
1 BEAR Short 
2 BULL Long 

Oder haben Ihnen Logik mit den Daten, bevor Sie den Datenrahmen zu erstellen:

import pandas as pd 
data = ["BULL","BEAR","BULL"] 
data2 = ["Long" if ele == "BULL" else "Short" for ele in data] 
df = pd.DataFrame(list(zip(data, data2)), columns=['A','B']) 

print(df) 
     A  B 
0 BULL Long 
1 BEAR Short 
2 BULL Long 

Für Ihre edit:

df = pd.DataFrame([['BULL APPLE X5',''],['BEAR APPLE X5',''],['BULL APPLE X5','']], columns=['A','B']) 

df["B"] = df["A"].map(lambda x: "Long" if "BULL" in x else "Short" if "BEAR" in x else "") 

print(df) 

      A  B 
0 BULL APPLE X5 Long 
1 BEAR APPLE X5 Short 
2 BULL APPLE X5 Long 

Oder fügen Sie einfach die Spalte nach:

df = pd.DataFrame(['BULL APPLE X5','BEAR APPLE X5','BLL APPLE X5'], columns=['A']) 

df["B"] = df["A"].map(lambda x: "Long" if "BULL" in x else "Short" if "BEAR" in x else "") 

print(df) 

Oder mit enthält:

df = pd.DataFrame([['BULL APPLE X5',''],['BEAR APPLE X5',''],['BULL APPLE X5','']], columns=['A','B']) 


df["B"][df['A'].str.contains("BULL")] = "Long" 
df["B"][df['A'].str.contains("BEAR")] = "Short" 

print(df) 
0 BULL APPLE X5 Long 
1 BEAR APPLE X5 Short 
2 BULL APPLE X5 Long 
+0

das funktioniert nur, wenn du nicht bei Bull bist, musst du ein Bär sein. Aber das ist nicht gerade die Bedingung des OP – joaquin

+0

@joaquin, das OP sagt nicht, dass es irgendeine andere Möglichkeit gibt, aber wenn es wäre, wäre es nicht zu schwer, die Logik dafür hinzuzufügen. –

+0

@PadraicCunningham Danke, ich habe das OP mit dem richtigen DataFrame korrigiert, um zukünftige Leser nicht zu verwirren. Sie können Ihre Antwort bearbeiten, wenn Sie möchten. Versuchen Sie Ihre Lösung – Winterflags

2

Auch zum Bestücken der df['B'] Sie das unten stehende Methode versuchen kann -

def applyFunc(s): 
    if s == 'BULL': 
     return 'Long' 
    elif s == 'BEAR': 
     return 'Short' 
    return '' 

df['B'] = df['A'].apply(applyFunc) 
df 
>> 
     A  B 
0 BULL Long 
1 BEAR Short 
2 BULL Long 

Was die apply funktioniert, ist das für jeden Zeilenwert von df['A'], ruft es die applyFunc Funktion mit dem Parameter als auf der Wert dieser Zeile, und der zurückgegebene Wert ist in der gleichen Zeile für df['B'], was wirklich passiert hinter der Szene ist ein bisschen anders, obwohl der Wert ist nicht direkt in df['B'] gesetzt, sondern eine neue Series wird erstellt und am Ende Die neue Serie wird df['B'] zugewiesen.

+0

Danke, ich habe das OP mit dem richtigen DataFrame korrigiert, um zukünftige Leser nicht zu verwirren. Sie können Ihre Antwort bearbeiten, wenn Sie möchten. – Winterflags

+1

Fertig, aktualisiert die Antwort. –

2

Sie str.extract für RegexMuster zur Suche verwenden könnte BULL|BEAR und dann Series.map verwenden, um die Saiten mit Long oder Short zu ersetzen :

In [50]: df = pd.DataFrame([['BULL APPLE X5',''],['BEAR APPLE X5',''],['BULL APPLE X5','']],columns=['A','B']) 

In [51]: df['B'] = df['A'].str.extract(r'(BULL|BEAR)').map({'BULL':'Long', 'BEAR':'Short'}) 

In [55]: df 
Out[55]: 
       A  B 
0 BULL APPLE X5 Long 
1 BEAR APPLE X5 Short 
2 BULL APPLE X5 Long 

Allerdings bildet die Zwischenstufe Ser ies mit str.extract ist ziemlich langsam im Vergleich zu 10.Mit IPython des %timeit zu Zeit die Benchmarks,

In [5]: df = pd.concat([df]*10000) 

In [6]: %timeit df['A'].str.extract(r'(BULL|BEAR)').map({'BULL':'Long', 'BEAR':'Short'}) 
10 loops, best of 3: 39.7 ms per loop 

In [7]: %timeit df["A"].map(lambda x: "Long" if "BULL" in x else "Short" if "BEAR" in x else "") 
100 loops, best of 3: 4.98 ms per loop 

Die Mehrheit der Zeit in str.extract ausgegeben wird:

In [8]: %timeit df['A'].str.extract(r'(BULL|BEAR)') 
10 loops, best of 3: 37.1 ms per loop 

, während der Anruf zu Series.map relativ schnell ist:

In [9]: x = df['A'].str.extract(r'(BULL|BEAR)') 

In [10]: %timeit x.map({'BULL':'Long', 'BEAR':'Short'}) 
1000 loops, best of 3: 1.82 ms per loop 
+0

Vielen Dank, Regex ist sehr nützlich.Wird auf jeden Fall in der Lage sein, das zu verwenden. – Winterflags

+0

Danke für das Hinzufügen der Zeit-Tests, sehr interessant. – Winterflags

Verwandte Themen