Ich habe ein Wörterbuch, das so aussieht: di = {1: "A", 2: "B"}
Ich würde es gerne auf die Spalte "col1" eines Datenrahmens anwenden, ähnlich:
col1 col2
0 w a
1 1 2
2 2 NaN
bekommen:
col1 col2
0 w a
1 A 2
2 B NaN
Wie kann ich das am besten machen? Aus einigen Gründen zeigt das Durchsuchen von Googeln nur Links, wie man Spalten aus Diktaten bildet und umgekehrt: - /
Sie können .replace
verwenden. Zum Beispiel:
>>> df = pd.DataFrame({'col2': {0: 'a', 1: 2, 2: np.nan}, 'col1': {0: 'w', 1: 1, 2: 2}})
>>> di = {1: "A", 2: "B"}
>>> df
col1 col2
0 w a
1 1 2
2 2 NaN
>>> df.replace({"col1": di})
col1 col2
0 w a
1 A 2
2 B NaN
oder direkt auf der Series
, d. h. df["col1"].replace(di, inplace=True)
.
map
kann viel schneller sein als replace
Wenn Ihr Wörterbuch mehr als ein paar Schlüssel enthält, kann die Verwendung von map
viel schneller als replace
sein. Es gibt zwei Versionen dieses Ansatzes, abhängig davon, ob Ihr Wörterbuch alle möglichen Werte erschöpfend abbildet (und auch, ob nicht übereinstimmende Werte beibehalten oder in NaNs konvertiert werden sollen):
In diesem Fall ist das Formular sehr einfach:
df['col1'].map(di) # note: if the dictionary does not exhaustively map all
# entries then non-matched entries are changed to NaNs
Obwohl map
am häufigsten eine Funktion als Argument verwendet, kann sie alternativ ein Wörterbuch oder eine Serie verwenden: Dokumentation für Pandas.series.map
Wenn Sie ein nicht erschöpfendes Mapping haben und die vorhandenen Variablen für Nichtübereinstimmungen beibehalten möchten, können Sie fillna
hinzufügen:
df['col1'].map(di).fillna(df['col1'])
wie in @ jpps Antwort hier: Werte in einer Pandaserie effizient über Wörterbuch ersetzen
Verwendung der folgenden Daten mit Pandas Version 0.23.1:
di = {1: "A", 2: "B", 3: "C", 4: "D", 5: "E", 6: "F", 7: "G", 8: "H" }
df = pd.DataFrame({ 'col1': np.random.choice( range(1,9), 100000 ) })
und mit %timeit
zu testen, scheint map
etwa 10x schneller zu sein als replace
.
Beachten Sie, dass Ihre Beschleunigung mit map
von Ihren Daten abhängt. Die größte Beschleunigung scheint mit großen Wörterbüchern und erschöpfenden Ersetzungen zu sein. Weitere ausführliche Benchmarks und Diskussionen finden Sie unter @jpp answer (oben verlinkt).
In Ihrer Frage ist ein bisschen mehrdeutig. Es gibt zumindest drei zwei interpretationen:
di
beziehen sich auf Indexwertedi
beziehen sich auf df['col1']
-Wertedi
beziehen sich auf Indexpositionen (nicht auf die Frage des OPs, sondern nur zum Spaß.)Nachfolgend finden Sie eine Lösung für jeden Fall.
Fall 1: Wenn die Schlüssel von di
auf Indexwerte verweisen sollen, können Sie die update
-Methode verwenden:
df['col1'].update(pd.Series(di))
Zum Beispiel,
import pandas as pd
import numpy as np
df = pd.DataFrame({'col1':['w', 10, 20],
'col2': ['a', 30, np.nan]},
index=[1,2,0])
# col1 col2
# 1 w a
# 2 10 30
# 0 20 NaN
di = {0: "A", 2: "B"}
# The value at the 0-index is mapped to 'A', the value at the 2-index is mapped to 'B'
df['col1'].update(pd.Series(di))
print(df)
erträge
col1 col2
1 w a
2 B 30
0 A NaN
Ich habe die Werte Ihres ursprünglichen Posts so geändert, dass klarer ist, was update
macht . Beachten Sie, wie die Schlüssel in di
Indexwerten zugeordnet werden. Die Reihenfolge der Indexwerte - dh der Index locations - spielt keine Rolle.
Fall 2: Wenn sich die Schlüssel in di
auf df['col1']
-Werte beziehen, zeigen @DanAllan und @DSM, wie dies mit replace
zu erreichen ist:
import pandas as pd
import numpy as np
df = pd.DataFrame({'col1':['w', 10, 20],
'col2': ['a', 30, np.nan]},
index=[1,2,0])
print(df)
# col1 col2
# 1 w a
# 2 10 30
# 0 20 NaN
di = {10: "A", 20: "B"}
# The values 10 and 20 are replaced by 'A' and 'B'
df['col1'].replace(di, inplace=True)
print(df)
erträge
col1 col2
1 w a
2 A 30
0 B NaN
Beachten Sie, wie in diesem Fall die Schlüssel in di
so geändert wurden, dass sie mit values in df['col1']
übereinstimmen.
Fall 3: Wenn sich die Schlüssel in di
auf Indexpositionen beziehen, können Sie verwenden
df['col1'].put(di.keys(), di.values())
schon seit
df = pd.DataFrame({'col1':['w', 10, 20],
'col2': ['a', 30, np.nan]},
index=[1,2,0])
di = {0: "A", 2: "B"}
# The values at the 0 and 2 index locations are replaced by 'A' and 'B'
df['col1'].put(di.keys(), di.values())
print(df)
erträge
col1 col2
1 A a
2 10 30
0 B NaN
Hier wurden die erste und die dritte Zeile geändert, da die Schlüssel in di
0
und 2
sind, die sich bei der 0-basierten Python-Indexierung auf die erste und dritte Position beziehen.
Hinzufügen zu dieser Frage, wenn in einem Datenframe mehr als eine Spalte neu zugeordnet werden muss:
def remap(data,dict_labels):
"""
This function take in a dictionnary of labels : dict_labels
and replace the values (previously labelencode) into the string.
ex: dict_labels = {{'col1':{1:'A',2:'B'}}
"""
for field,values in dict_labels.items():
print("I am remapping %s"%field)
data.replace({field:values},inplace=True)
print("DONE")
return data
Ich hoffe es kann für jemanden nützlich sein.
Prost
DSM hat die akzeptierte Antwort, aber die Kodierung scheint nicht für jeden zu funktionieren. Hier ist eine Version, die mit der aktuellen Version von Pandas funktioniert (0.23.4 Stand 8/2018):
import pandas as pd
df = pd.DataFrame({'col1': [1, 2, 2, 3, 1],
'col2': ['negative', 'positive', 'neutral', 'neutral', 'positive']})
conversion_dict = {'negative': -1, 'neutral': 0, 'positive': 1}
df['converted_column'] = df['col2'].replace(conversion_dict)
print(df.head())
Sie werden sehen wie es aussieht:
col1 col2 converted_column
0 1 negative -1
1 2 positive 1
2 2 neutral 0
3 3 neutral 0
4 1 positive 1
Die Dokumente für pandas.DataFrame.replace sind hier .
Oder apply
:
df['col1'].apply(lambda x: {1: "A", 2: "B"}.get(x,x))
Demo:
>>> df['col1']=df['col1'].apply(lambda x: {1: "A", 2: "B"}.get(x,x))
>>> df
col1 col2
0 w a
1 1 2
2 2 NaN
>>>
Ein nativerer Pandas-Ansatz besteht darin, eine Ersetzungsfunktion wie folgt anzuwenden:
def multiple_replace(dict, text):
# Create a regular expression from the dictionary keys
regex = re.compile("(%s)" % "|".join(map(re.escape, dict.keys())))
# For each match, look-up corresponding value in dictionary
return regex.sub(lambda mo: dict[mo.string[mo.start():mo.end()]], text)
Nachdem Sie die Funktion definiert haben, können Sie sie auf Ihren Datenrahmen anwenden.
di = {1: "A", 2: "B"}
df['col1'] = df.apply(lambda row: multiple_replace(di, row['col1']), axis=1)
Eine nette Komplettlösung, die eine Karte Ihrer Klassenbeschriftungen enthält:
labels = features['col1'].unique()
labels_dict = dict(Zip(labels, range(len(labels))))
features = features.replace({"col1": labels_dict})
Auf diese Weise können Sie jederzeit auf die ursprüngliche Klassenbezeichnung von labels_dict verweisen.