Die meisten Informationen, die ich gefunden habe, waren nicht in Python> Pandas> Dataframe, daher die Frage.
Ich möchte eine ganze Zahl zwischen 1 und 12 in einen abgekürzten Monatsnamen umwandeln.
Ich habe eine DF, die wie folgt aussieht:
client Month
1 sss 02
2 yyy 12
3 www 06
Ich möchte, dass der DF so aussieht:
client Month
1 sss Feb
2 yyy Dec
3 www Jun
Sie können dies effizient tun, indem Sie calendar.month_abbr
und df[col].apply()
kombinieren.
import calendar
df['Month'] = df['Month'].apply(lambda x: calendar.month_abbr[x])
Eine Möglichkeit dazu ist die apply
-Methode im Dataframe, aber dazu benötigen Sie eine Karte, um die Monate zu konvertieren. Sie können dies entweder mit einer Funktion/einem Wörterbuch oder mit Pythons eigener Datetime tun.
Mit der Datumszeit wäre es ungefähr so:
def mapper(month):
date = datetime.datetime(2000, month, 1) # You need a dateobject with the proper month
return date.strftime('%b') # %b returns the months abbreviation, other options [here][1]
df['Month'].apply(mapper)
In ähnlicher Weise können Sie Ihre eigene Karte für benutzerdefinierte Namen erstellen. Es würde so aussehen:
months_map = {01: 'Jan', 02: 'Feb'}
def mapper(month):
return months_map[month]
Offensichtlich müssen Sie diese Funktionen nicht explizit definieren und könnten eine lambda
direkt in der Apply-Methode verwenden.
Verwenden Sie dazu die Funktion strptime
und lambda
:
from time import strptime
df['Month'] = df['Month'].apply(lambda x: strptime(x,'%b').tm_mon)
Sie können dies problemlos mit einer Spalte anwenden.
import pandas as pd
df = pd.DataFrame({'client':['sss', 'yyy', 'www'], 'Month': ['02', '12', '06']})
look_up = {'01': 'Jan', '02': 'Feb', '03': 'Mar', '04': 'Apr', '05': 'May',
'06': 'Jun', '07': 'Jul', '08': 'Aug', '09': 'Sep', '10': 'Oct', '11': 'Nov', '12': 'Dec'}
df['Month'] = df['Month'].apply(lambda x: look_up[x])
df
Month client
0 Feb sss
1 Dec yyy
2 Jun www
Da die abgekürzten Monatsnamen die ersten drei Buchstaben ihres vollen Namens sind, könnten wir zuerst die Month
-Spalte in datetime
konvertieren und dann dt.month_name()
verwenden, um den vollständigen Monatsnamen zu erhalten, und schließlich die str.slice()
-Methode verwenden, um die ersten drei Buchstaben zu erhalten, die alle Pandas und verwenden nur in einer Codezeile:
df['Month'] = pd.to_datetime(df['Month'], format='%m').dt.month_name().str.slice(stop=3)
df
Month client
0 Feb sss
1 Dec yyy
2 Jun www
def mapper(month):
return month.strftime('%b')
df['Month'] = df['Month'].apply(mapper)
Referenz:
Das calendar
Modul ist nützlich, aber calendar.month_abbr
ist arrayartig: Es kann nicht direkt vektorisiert verwendet werden. Für ein effizientes Mapping können Sie ein Wörterbuch erstellen und dann pd.Series.map
verwenden:
import calendar
d = dict(enumerate(calendar.month_abbr))
df['Month'] = df['Month'].map(d)
Performance-Benchmarking zeigt einen ~ 130x-Leistungsunterschied:
import calendar
d = dict(enumerate(calendar.month_abbr))
mapper = calendar.month_abbr.__getitem__
np.random.seed(0)
n = 10**5
df = pd.DataFrame({'A': np.random.randint(1, 13, n)})
%timeit df['A'].map(d) # 7.29 ms per loop
%timeit df['A'].map(mapper) # 946 ms per loop
Nachdem ich all diese Daten an einem großen Datensatz getestet habe, habe ich festgestellt, dass folgende am schnellsten ist:
import calendar
def month_mapping():
# I'm lazy so I have a stash of functions already written so
# I don't have to write them out every time. This returns the
# {1:'Jan'....12:'Dec'} dict in the laziest way...
abbrevs = {}
for month in range (1, 13):
abbrevs[month] = calendar.month_abbr[month]
return abbrevs
abbrevs = month_mapping()
df['Month Abbrev'} = df['Date Col'].dt.month.map(mapping)