【问题标题】:python/pandas: convert month int to month namepython/pandas:将月份 int 转换为月份名称
【发布时间】:2016-10-04 04:00:11
【问题描述】:

我发现的大部分信息都不在 python>pandas>dataframe 中,因此是这个问题。

我想将 1 到 12 之间的整数转换为缩写的月份名称。

我有一个看起来像这样的 df:

   client Month
1  sss    02
2  yyy    12
3  www    06

我希望 df 看起来像这样:

   client Month
1  sss    Feb
2  yyy    Dec
3  www    Jun

【问题讨论】:

    标签: python date pandas dataframe monthcalendar


    【解决方案1】:

    您可以通过结合calendar.month_abbrdf[col].apply() 有效地做到这一点

    import calendar
    df['Month'] = df['Month'].apply(lambda x: calendar.month_abbr[x])
    

    【讨论】:

    • 请注意,此解决方案类似于 Python 级循环中的 list.__getitem__,即它没有利用 Pandas 可用的矢量化功能。根据this answer,提取到字典然后映射效率更高。
    • 当你有 pandas 自己的 month_name() 函数时,我认为这不是一个好主意。
    【解决方案2】:

    由于月份名称的缩写是其全名的前三个字母,我们可以先将Month列转换为datetime,然后使用dt.month_name()得到完整的月份名称,最后使用str.slice()方法获取前三个字母,全部使用 pandas 并且仅在一行代码中:

    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
    

    【讨论】:

      【解决方案3】:

      calendar 模块很有用,但calendar.month_abbr 类似于数组:它不能直接以矢量化方式使用。为了高效的映射,你可以构造一个字典,然后使用pd.Series.map

      import calendar
      d = dict(enumerate(calendar.month_abbr))
      df['Month'] = df['Month'].map(d)
      

      性能基准测试显示约 130 倍的性能差异:

      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
      

      【讨论】:

        【解决方案4】:

        您可以通过应用列轻松做到这一点。

        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
        

        【讨论】:

          【解决方案5】:
          def mapper(month):
             return month.strftime('%b') 
          
          df['Month'] = df['Month'].apply(mapper)
          

          参考:

          【讨论】:

            【解决方案6】:

            一种方法是使用数据框中的apply 方法,但要做到这一点,您需要一张地图来转换月份。您可以使用函数/字典或 Python 自己的日期时间来做到这一点。

            日期时间类似于:

            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)
            


            以类似的方式,您可以为自定义名称构建自己的地图。它看起来像这样:

            months_map = {01: 'Jan', 02: 'Feb'}
            def mapper(month):
                return months_map[month]
            


            显然,您不需要显式定义此函数,可以直接在 apply 方法中使用lambda

            【讨论】:

              【解决方案7】:

              为此使用strptimelambda 函数:

              from time import strptime
              df['Month'] = df['Month'].apply(lambda x: strptime(x,'%b').tm_mon) 
              

              【讨论】:

                【解决方案8】:

                假设我们有一个这样的 DF,并且 Date 已经是 DateTime 格式:

                df.head(3)
                
                
                            value   
                date        
                2016-05-19  19736   
                2016-05-26  18060   
                2016-05-27  19997   
                

                然后我们可以像这样轻松提取月份编号和月份名称:

                df['month_num'] = df.index.month
                df['month'] = df.index.month_name()
                
                
                            value   year    month_num  month
                date                
                2017-01-06  37353   2017    1          January
                2019-01-06  94108   2019    1          January
                2019-01-05  77897   2019    1          January
                2019-01-04  94514   2019    1          January
                

                【讨论】:

                  【解决方案9】:

                  使用日期时间对象方法

                  我很惊讶这个答案没有使用strftime的解决方案

                  注意,在使用strftime 方法之前,您需要有一个有效的日期时间对象,使用pd.to_datetime(df['date_column']) 将您的目标列转换为日期时间对象。

                  import pandas as pd 
                  
                  dates = pd.date_range('01-Jan 2020','01-Jan 2021',freq='M')
                  
                  df = pd.DataFrame({'dates' : dates})
                  df['month_name'] = df['dates'].dt.strftime('%b')
                  
                     dates month_name
                  0  2020-01-31        Jan
                  1  2020-02-29        Feb
                  2  2020-03-31        Mar
                  3  2020-04-30        Apr
                  4  2020-05-31        May
                  5  2020-06-30        Jun
                  6  2020-07-31        Jul
                  7  2020-08-31        Aug
                  8  2020-09-30        Sep
                  9  2020-10-31        Oct
                  10 2020-11-30        Nov
                  11 2020-12-31        Dec
                  

                  另一种方法是使用dt.month_name() 对名称进行切片

                  df['month_name_str_slice'] = df['dates'].dt.month_name().str[:3]
                  
                          dates month_name month_name_str_slice
                  0  2020-01-31        Jan                  Jan
                  1  2020-02-29        Feb                  Feb
                  2  2020-03-31        Mar                  Mar
                  3  2020-04-30        Apr                  Apr
                  4  2020-05-31        May                  May
                  5  2020-06-30        Jun                  Jun
                  6  2020-07-31        Jul                  Jul
                  7  2020-08-31        Aug                  Aug
                  8  2020-09-30        Sep                  Sep
                  9  2020-10-31        Oct                  Oct
                  10 2020-11-30        Nov                  Nov
                  11 2020-12-31        Dec                  Dec
                  

                  【讨论】:

                    【解决方案10】:

                    在大型数据集上测试了所有这些,我发现以下是最快的:

                    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)
                    

                    【讨论】:

                      【解决方案11】:

                      您可以使用 Pandas month_name() 函数。示例:

                      >>> idx = pd.date_range(start='2018-01', freq='M', periods=3)
                      >>> idx
                      DatetimeIndex(['2018-01-31', '2018-02-28', '2018-03-31'],
                                        dtype='datetime64[ns]', freq='M')
                      >>> idx.month_name()
                      Index(['January', 'February', 'March'], dtype='object')
                      

                      更多详情请访问this link

                      【讨论】:

                        【解决方案12】:

                        最好的方法是使用month_name(),正如
                        所评论的那样 Nurul Akter Towhid。

                        df['月份'] = df.Month.dt.month_name()

                        【讨论】:

                          猜你喜欢
                          • 1970-01-01
                          • 2015-08-07
                          • 1970-01-01
                          • 1970-01-01
                          • 1970-01-01
                          • 1970-01-01
                          • 2021-10-03
                          • 1970-01-01
                          相关资源
                          最近更新 更多