计算1年内每个ID的行数

时间:2017-09-07 11:51:06

标签: python pandas

我有一个像这样的pandas数据框

Date        ID
01/01/2016  a
05/01/2016  a
10/05/2017  a
05/05/2014  b
07/09/2014  b
12/08/2017  b

我需要做的是添加一个列,显示去年发生的每个ID的条目数,另一列显示下一年的数字。我写了一些可怕的代码,遍历整个数据帧(数百万行)并进行计算,但必须有更好的方法!

3 个答案:

答案 0 :(得分:3)

我认为首先需要使用between boolean indexing进行过滤,然后groupby并汇总size

输出concat并添加reindex以添加由0填充的缺失行:

print (df)
         Date ID
0  01/01/2016  a
1  05/01/2016  a
2  10/05/2017  a
3  05/05/2018  b
4  07/09/2014  b
5  07/09/2014  c
6  12/08/2018  b
#convert to datetime (if first number is day, add parameter dayfirst)
df['Date'] = pd.to_datetime(df['Date'], dayfirst=True)
now = pd.datetime.today()
print (now)

oneyarbeforenow =  now - pd.offsets.DateOffset(years=1)
oneyarafternow =  now + pd.offsets.DateOffset(years=1)

#first filter
a = df[df['Date'].between(oneyarbeforenow, now)].groupby('ID').size()
b = df[df['Date'].between(now, oneyarafternow)].groupby('ID').size()
print (a)
ID
a    1
dtype: int64

print (b)
ID
b    2
dtype: int64

df1 = pd.concat([a,b],axis=1).fillna(0).astype(int).reindex(df['ID'].unique(),fill_value=0)
print (df1)
   0  1
a  1  0
b  0  2
c  0  0

编辑:

如果需要按照第一个日期比较每个日期,则每个组添加或减去year offset需要具有条件的自定义函数和sum真则:

offs = pd.offsets.DateOffset(years=1)

f = lambda x: pd.Series([(x > x.iat[-1] - offs).sum(), \
                        (x < x.iat[-1] + offs).sum()], index=['last','next'])
df = df.groupby('ID')['Date'].apply(f).unstack(fill_value=0).reset_index()
print (df)
  ID  last  next
0  a     1     3
1  b     3     2
2  c     1     1

答案 1 :(得分:1)

In [19]: x['date'] = pd.to_datetime( x['date']) # convert string date to datetime pd object
In [20]: x['date'] = x['date'].dt.year # get year from the date

In [21]: x
Out[21]: 
   date id
0  2016  a
1  2016  a
2  2017  a
3  2014  b
4  2014  b
5  2017  b


In [27]: x.groupby(['date','id']).size() # group by both columns
Out[27]: 
date  id
2014  b     2
2016  a     2
2017  a     1
      b     1

答案 2 :(得分:0)

使用const可以解决多年之间缺失的问题。看到。年-2015

resample

如果您只需要列中的年份

,请使用In [550]: df.set_index('Date').groupby('ID').resample('Y').size().unstack(fill_value=0) Out[550]: Date 2014-12-31 2015-12-31 2016-12-31 2017-12-31 ID a 0 0 2 1 b 2 0 0 1
rename