问题:给定一个包含多个条目的数据框和一个" 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"使用df
在months
上运行,但有点迷失...
ps:
pd.__version__
'0.14.0'
帮助表示赞赏。
答案 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')对我不起作用。 但是,我希望它能实现你想要的。