从ISO 8601星期几对pandas数据框进行排序

问题描述 投票:0回答:3

我想用包含一周中某一天的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输入。

pandas datetime iso8601
3个回答
2
投票

我知道如何处理这种情况最干净的方法是使用daycategory列转换为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]

2
投票

我建议使用mapnp.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

2
投票

我曾尝试过其他东西,所以只发贴它:

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
© www.soinside.com 2019 - 2024. All rights reserved.