我想用包含一周中某一天的ISO-8601表示的列对Pandas数据帧进行排序。
df = pd.DataFrame([
{ 'day': 'Mon', 'value': 13 },
{ 'day': 'Wed', 'value': 24 },
{ 'day': 'Fri', 'value': 52 },
{ 'day': 'Sun', 'value': 56 },
{ 'day': 'Sat', 'value': 42 },
{ 'day': 'Thu', 'value': 84 },
{ 'day': 'Tue', 'value': 59 }
])
df['dt_'] = pd.to_datetime(df['day'], format='%a', errors='coerce')
df = df.sort_values('dt_')
>>> print(df)
day value dt_
0 Mon 13 1900-01-01
1 Wed 24 1900-01-01
2 Fri 52 1900-01-01
3 Sun 56 1900-01-01
4 Sat 42 1900-01-01
5 Thu 84 1900-01-01
6 Tue 59 1900-01-01
显然,预期的行为是使数据框按Mon Tue Wed Thu Fri Sat Sun
排序。根据http://strftime.org/,这种%a
格式似乎是正确的。
除了包含day -> number
字典的黑客之外,有没有更清洁的方法来实现这一目标?
这里的例子是缩写的星期几(Dy
ISO-8601),但理想情况下,我会采用一般解决方案来处理任何ISO-8601输入。
我知道如何处理这种情况最干净的方法是使用day
将category
列转换为pandas ordered=True
数据类型,手动强制执行所需的排序顺序:
df['day'] = pd.Categorical(df['day'], ordered=True,
categories=['Mon', 'Tue', 'Wed', 'Thu',
'Fri', 'Sat', 'Sun'])
df = df.sort_values(by='day').reset_index(drop=True)
df
day value
0 Mon 13
1 Tue 59
2 Wed 24
3 Thu 84
4 Fri 52
5 Sat 42
6 Sun 56
day
列现在有dtype category
和定义的排序顺序:
df['day']
0 Mon
1 Tue
2 Wed
3 Thu
4 Fri
5 Sat
6 Sun
Name: day, dtype: category
Categories (7, object): [Mon < Tue < Wed < Thu < Fri < Sat < Sun]
我建议使用map
和np.argsort
而不更改原始数据类型,这在真实单词中更安全
dayOfWeek={'Mon':0, 'Tue':1,'Wed':2,'Thu':3,'Fri':4,'Sat':5,'Sun':6}
df.iloc[np.argsort(df.day.map(dayOfWeek)),:]
day value
0 Mon 13
6 Tue 59
1 Wed 24
5 Thu 84
2 Fri 52
4 Sat 42
3 Sun 56
我曾尝试过其他东西,所以只发贴它:
import calendar
d={i[:3]:e+1 for e,i in enumerate(list(calendar.day_name))}
#{'Mon': 1, 'Tue': 2, 'Wed': 3, 'Thu': 4, 'Fri': 5, 'Sat': 6, 'Sun': 7}
df['day_num']=df.day.map(d)
df.sort_values('day_num')
day value dt_ day_num
0 Mon 13 1900-01-01 1
6 Tue 59 1900-01-01 2
1 Wed 24 1900-01-01 3
5 Thu 84 1900-01-01 4
2 Fri 52 1900-01-01 5
4 Sat 42 1900-01-01 6
3 Sun 56 1900-01-01 7