计算落入熊猫时期的行

时间:2018-05-12 17:11:35

标签: python pandas

我有一个看起来像这样的数据框

customer  Start_date  End_date
100       2016-06-01  2018-01-01
101       2017-06-01  2019-01-01
102       2016-04-01  2017-04-01
103       2015-06-03  2016-01-01
104       2016-06-01  2018-01-01

现在我想创建一个带有句点索引的数据框,该索引的列数包含每个句点的客户数量,如下所示:

Period    Customers
2017-01   3
2017-02   5
2017-03   8
2017-04   9

我已经编写了一个自定义循环来执行此操作,但它非常低效。必须有一种更快的方法来使用pandas功能来完成这项工作。非常感谢任何帮助!

2 个答案:

答案 0 :(得分:2)

您可以按to_period创建月份期间,列表理解每个customer的所有期间和groupby的最后nunique

df['Start_date'] = pd.to_datetime(df['Start_date']).dt.to_period('m')
df['End_date'] = pd.to_datetime(df['End_date']).dt.to_period('m')
#if want exclude last periods per rows subtract 1
#df['End_date'] = pd.to_datetime(df['End_date']).dt.to_period('m') - 1

L = [(a, d) for a,b,c in df.values for d in pd.period_range(b,c, freq='m')]

for all unique customers per period
df = pd.DataFrame(L, columns=['v','d']).groupby('d')['v'].nunique()
print (df.head(10))
d
2015-06    1
2015-07    1
2015-08    1
2015-09    1
2015-10    1
2015-11    1
2015-12    1
2016-01    1
2016-04    1
2016-05    1
Freq: M, dtype: int64

包含测试解决方案的不同数据的示例:

print (df)
   customer Start_date   End_date
0       100 2016-03-01 2016-06-01
1       100 2016-08-01 2016-10-01
2       102 2016-04-01 2017-01-01
3       103 2016-06-03 2016-01-01
4       103 2016-06-01 2016-05-01

df['Start_date'] = pd.to_datetime(df['Start_date']).dt.to_period('m')
df['End_date'] = pd.to_datetime(df['End_date']).dt.to_period('m')

L = [(a, d) for a,b,c in df.values for d in pd.period_range(b,c, freq='m')]
df = pd.DataFrame(L, columns=['v','d']) 
print (df)
      v       d
0   100 2016-03
1   100 2016-04
2   100 2016-05
3   100 2016-06
4   100 2016-08
5   100 2016-09
6   100 2016-10
7   102 2016-04
8   102 2016-05
9   102 2016-06
10  102 2016-07
11  102 2016-08
12  102 2016-09
13  102 2016-10
14  102 2016-11
15  102 2016-12
16  102 2017-01

df1 = df.groupby('d')['v'].nunique().reset_index()
print (df1)
         d  v
0  2016-03  1
1  2016-04  2
2  2016-05  2
3  2016-06  2
4  2016-07  1
5  2016-08  2
6  2016-09  2
7  2016-10  2
8  2016-11  1
9  2016-12  1
10 2017-01  1

答案 1 :(得分:1)

DT[,ReplB := all(diff(mapply(function(x)which(letters==x),place)) == 1),by=id][
  !(ReplB & place == "c"),.(id, place = ifelse(place=="b" & ReplB,"z",place),seq)]
#    id place seq
# 1:  1     a   1
# 2:  1     z   2
# 3:  1     d   4
# 4:  2     a   1
# 5:  2     b   2
# 6:  2     d   3
# 7:  2     e   4