Сортировать кадр данных панды по ISO 8601 день недели - PullRequest
0 голосов
/ 17 марта 2019

Я хотел бы отсортировать кадр данных Pandas по столбцу, содержащему представление дня недели в ISO-8601.

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 представляется правильным.

Помимо хака, который будет заключаться в том, чтобы иметь Dict day -> number, есть ли более чистый способ достичь этого?

Здесь приведен пример с сокращенным днем ​​недели (Dy ISO-8601), но в идеале я хотел бы найти общее решение для любого ввода ISO-8601.

Ответы [ 3 ]

2 голосов
/ 17 марта 2019

Я пробовал что-то еще, поэтому просто опубликовал это:

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
2 голосов
/ 17 марта 2019

Я рекомендую использовать 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
2 голосов
/ 17 марта 2019

Самый простой способ, которым я знаю, как справиться с этой ситуацией, - это преобразовать столбец day в тип данных pandas category с 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]
...