Python 指定外部订单时,按日期时间月排序行

Python 指定外部订单时,按日期时间月排序行,python,pandas,datetime,Python,Pandas,Datetime,所以我在订购我的数据帧时遇到了一点困难,我尝试过使用question,但并没有成功地让它工作。我拥有的是一个数据帧nudf如下所示: date level_1 0 0 2016-10-01 00:00:00 0.0 74.00 1 2016-10-01 00:30:00 0.5 72 2 2016-10-01 01:00:00 1.0 70 3

所以我在订购我的数据帧时遇到了一点困难,我尝试过使用question,但并没有成功地让它工作。我拥有的是一个数据帧
nudf
如下所示:

                     date  level_1      0 
0     2016-10-01 00:00:00      0.0  74.00    
1     2016-10-01 00:30:00      0.5     72    
2     2016-10-01 01:00:00      1.0     70    
3     2016-10-01 01:30:00      1.5     64    
4     2016-10-01 02:00:00      2.0     63    
5     2016-10-01 02:30:00      2.5     60    
...                   ...      ...    ...   
19003 2017-09-31 21:30:00     21.5    129    
19004 2017-09-31 22:00:00     22.0    118    
19005 2017-09-31 22:30:00     22.5    106  
19006 2017-09-31 23:00:00     23.0     84    
19007 2017-09-31 23:30:00     23.5     76    
我想做的是按外部月份顺序对行进行排序:

[4,5,6,7,8,9,10,11,12,1,2,3]

这是上个月以来的最后12个月。我想忽略年份,并按照上面的顺序排列每个月的行块

例如,给定以下行:

0     2016-02-01 00:00:00      0.0  74.00    
1     2016-02-01 00:30:00      0.5     72    
2     2016-03-01 01:00:00      1.0     70    
3     2016-03-01 01:30:00      1.5     64    
4     2017-04-01 02:00:00      2.0     63    
5     2017-04-01 02:30:00      2.5     60  
结果应该是:

4     2017-04-01 02:00:00      2.0     63    
5     2017-04-01 02:30:00      2.5     60
0     2016-02-01 00:00:00      0.0  74.00    
1     2016-02-01 00:30:00      0.5     72    
2     2016-03-01 01:00:00      1.0     70    
3     2016-03-01 01:30:00      1.5     64      
我试过:

nudf['month'] = nudf.apply(lambda row: row.date.month, axis=1)
nudf.month = nudf.month.astype("category")
nudf.month.cat.set_categories([x.month for x in reversed(_get_last_x_months(12))], inplace=True)

nudf.sort_values(["month"], inplace=True)
但这一天和小时的秩序并没有得到维持

您可以使用单独的、
argsort
iloc

另外,请注意,我使用了
kind='mergesort'
,因为
mergesort
是一种“稳定”的排序算法,将保持等价值行的相对顺序

mcats = [4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3]
nudf.iloc[pd.Categorical(nudf.date.dt.month, mcats, True).argsort(kind='mergesort')]

                 date  level_1     0
4 2017-04-01 02:00:00      2.0  63.0
5 2017-04-01 02:30:00      2.5  60.0
0 2016-02-01 00:00:00      0.0  74.0
1 2016-02-01 00:30:00      0.5  72.0
2 2016-03-01 01:00:00      1.0  70.0
3 2016-03-01 01:30:00      1.5  64.0

您也可以添加列

mcats = [4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3]
nudf = nudf.assign(month=pd.Categorical(nudf.date.dt.month, mcats, True))
nudf.sort_values('month', kind='mergesort')

                 date  level_1     0 month
4 2017-04-01 02:00:00      2.0  63.0     4
5 2017-04-01 02:30:00      2.5  60.0     4
0 2016-02-01 00:00:00      0.0  74.0     2
1 2016-02-01 00:30:00      0.5  72.0     2
2 2016-03-01 01:00:00      1.0  70.0     3
3 2016-03-01 01:30:00      1.5  64.0     3

如果我们尝试按月份排序,然后按日期排序,则不需要指定稳定的排序,只需按两列排序即可

mcats = [4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3]
nudf = nudf.assign(month=pd.Categorical(nudf.date.dt.month, mcats, True))
nudf.sort_values(['month', 'date'])
或者,我们可以使用
np.lexsort
返回基于多个数组的排序排列,而不是
argsort
答案

mcats = [4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3]
nudf.iloc[np.lexsort(
    [nudf.date, pd.Categorical(nudf.date.dt.month, mcats, True)]
)]

您可以使用
%
完成订购。但要获得所需的输出,首先要按日期时间排序

nudf.sort_values(by='date', inplace=True)

mcats = [x.month for x in reversed(_get_last_x_months(12))]
#[4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3]
nudf['m_fake'] = (nudf.date.dt.month+(12-mcats[0]))%12
nudf.sort_values(by='m_fake')

#                 date  val1  val2  m_fake
#4 2017-04-01 02:00:00   2.0    63       0
#5 2017-04-01 02:30:00   2.5    60       0
#0 2016-02-01 00:00:00   0.0    74       10
#1 2016-02-01 00:30:00   0.5    72       10
#2 2016-03-01 01:00:00   1.0    70       11
#3 2016-03-01 01:30:00   1.5    64       11
您可以使用更改值并对列重新排序

# creates an int value based on the date using .dt.month (must be a date type)
df['month_value'] = df['date'].dt.month

# creates a dictionary that will remap the values
new_order = {4:1, 5:2, 6:3, 7:4, 8:5, 9:6, 10:7, 11:8, 12:9, 1:10, 2:11, 3:12}

# creates a new column based on the mapping
df['new_value'] = df['month_value'].map(new_order)

# sorts the values based on the new column
df.sort_values(by='new_value')

           date  month_value  new_value
4 2017-04-01            4          1
5 2017-04-01            4          1
0 2016-02-01            2         11
1 2016-02-01            2         11
2 2016-03-01            3         12
3 2016-03-01            3         12

排序是由
[x.month for x in reversed(_get_last_x_months(12))]生成的,所以理想情况下我想使用它。好的,那么你只需要做12个排序[0]就不用再担心了,因为在更大的数据集上,有些天是无序的。这是因为在大文件中,它们没有按日期排序,而在这个例子中,他们是。我只是更新了,先根据日期排序,然后应用月份排序。那应该可以。是的,那是我的错误,你的答案看起来也很有效-谢谢你的帮助,另一个答案排在第一位,但这也是一个很好的解决方案。另一个我从来不知道的方便的东西。非常有趣的答案!我想知道订单是怎么运作的。。。我会给它一个测试,你可以看到,顺序是不正确的大文件,我有。我改变了我的帖子,以指定一个稳定的排序算法。看看这是否有帮助。与mergesort添加完美配合。非常感谢。