熊猫,绝对月份

时间:2014-10-20 08:51:23

标签: python-2.7 pandas group-by dataframe

问题:给定一个包含多个条目的数据框和一个" date" %Y%m%d形式的列(即yyyy-mm-dd;这些条目以字符串形式出现)什么是计算快速的方式将列添加到由月份的词典顺序组成的数据框? / p>

为什么在StackOverflow :给定指定的年份和月份,上述排序允许人们相对于指定月份轻松上升或下降任意数月。我有一个工作的临时解决方案,但想象这个问题在以前已经优雅地解决了。

上下文:举例来说,给定数据框df:

         date  user
0  2011-10-06     1
1  2011-09-01     2
2  2011-11-05     3
3  2012-01-01     1
4  2012-01-01     2
5  2012-01-02     3

所需的输出是:

         date  user  absmonth
0  2011-10-06     1         2
1  2011-09-01     2         1
2  2011-11-05     3         3
3  2012-01-01     1         4
4  2012-01-01     2         4
5  2012-01-02     3         4

我尝试了什么

1)我做了一个adhoc def,设定了'absmonth'的价值。基于简单的算术;每行通过df.loc[row, 'absmonth'] = ...。这"工作"但计算上非常慢。

2)使用groupby:

df['newdate']=pd.to_datetime(df['date'],format='%Y-%m-%d') 
df = df.set_index('newdate')
monthsgroup = df.groupby(df.index.month, df.index.year)

产生错误:

    axis = self._AXIS_ALIASES.get(axis, axis)
TypeError: unhashable type: 'numpy.ndarray'

还有:

months = df.gropuby(df.index.month)
len(months)
4

此时,我应该可以使用类似" apply"使用dfmonths上运行,但有点迷失...

ps:

pd.__version__
'0.14.0'

帮助表示赞赏。

2 个答案:

答案 0 :(得分:1)

我认为“申请”是一个很好的方式。

我从头到尾提供我目前的解决方案。我想我已经通过现在应用方法'min'来修正排名以获得所需的结果。

import pandas as pd

x = [{'date':'2011-10-06', 'user':1}, {'date':'2011-09-01', 'user':2},{'date':'2011-11-05', 'user':3}, {'date':'2012-01-01', 'user':1},{'date':'2012-01-01', 'user':2}, {'date':'2012-01-02', 'user':3}]

dx = pd.DataFrame(x)

dx['date'] = pd.to_datetime(dx['date'], format='%Y-%m-%d')

def get_ym(s):
  s = str(s)
  s = s[:7]
  s = s.replace('-','')
  return int(s)


dx['absmonth'] = dx['date'].apply(get_ym)
dx['absmonth'] = dx['absmonth'].rank(method='min')

-----
dx = 
        date  user  absmonth
0 2011-10-06     1  2
1 2011-09-01     2  1
2 2011-11-05     3  3
3 2012-01-01     1  4
4 2012-01-01     2  4
5 2012-01-02     3  4

如果有人有一个更流畅的解决方案,例如使用groupby,我都是耳朵。

更新: DSM慷慨地提出了以下解决方案,这是我的方法的紧凑版本,使用'密集'以1为增量排名:

dx['absmonth'] = dx['date'].str.split('-').str[:2].rank('dense')

答案 1 :(得分:0)

这个怎么样?

df['absmonth'] = df.date
dict = df.absmonth.unique()
dict.sort()
df.absmonth.replace(dict,range(1,len(dict)+1),inplace=True)

修改如果您希望使用日期而不是在结尾处进行格式化:

df['absmonth'] = df.date.apply(lambda x: np.datetime64(x, 'M'))
dict = df.absmonth.unique()
dict.sort()
df.absmonth.replace(dict,range(1,len(dict)+1),inplace=True)
df.absmonth=df.absmonth.astype(int)

我认为应该存在一种方法来避免使用apply但我没有找到它。 Pandas.to_datetime(df ['date'],format ='%Y-%m-%d',unit ='M')对我不起作用。 但是,我希望它能实现你想要的。

相关问题