Python和Pandas - 按天分组并统计每天数量

44

我刚接触pandas,目前还不知道如何排列我的时间序列,请看下面:

date & time of connection
19/06/2017 12:39
19/06/2017 12:40
19/06/2017 13:11
20/06/2017 12:02
20/06/2017 12:04
21/06/2017 09:32
21/06/2017 18:23
21/06/2017 18:51
21/06/2017 19:08
21/06/2017 19:50
22/06/2017 13:22
22/06/2017 13:41
22/06/2017 18:01
23/06/2017 16:18
23/06/2017 17:00
23/06/2017 19:25
23/06/2017 20:58
23/06/2017 21:03
23/06/2017 21:05

这是一个包含130k行的数据集示例,我尝试使用以下代码:

df.groupby('date & time of connection')['date & time of connection'].apply(list)

但我感觉这还不够。

我认为我应该:

  • 创建一个字典,将索引从dd/mm/yyyy转换到dd/mm/yyyy
  • 将“date & time of connection”类型dateTime转换为Date
  • 对“date & time of connection”的日期进行分组和计数
  • 将我计算出来的数字放入字典中?

你觉得我的逻辑怎么样?你知道一些教程吗?非常感谢!

3个回答

40

你可以使用dt.floor将内容转换为date,然后使用value_counts或者size进行分组统计:

df = (pd.to_datetime(df['date & time of connection'])
       .dt.floor('d')
       .value_counts()
       .rename_axis('date')
       .reset_index(name='count'))
print (df)
        date  count
0 2017-06-23      6
1 2017-06-21      5
2 2017-06-19      3
3 2017-06-22      3
4 2017-06-20      2
或者:
s = pd.to_datetime(df['date & time of connection'])
df = s.groupby(s.dt.floor('d')).size().reset_index(name='count')
print (df)
  date & time of connection  count
0                2017-06-19      3
1                2017-06-20      2
2                2017-06-21      5
3                2017-06-22      3
4                2017-06-23      6

时间:

np.random.seed(1542)

N = 220000
a = np.unique(np.random.randint(N, size=int(N/2)))
df = pd.DataFrame(pd.date_range('2000-01-01', freq='37T', periods=N)).drop(a)
df.columns = ['date & time of connection']
df['date & time of connection'] = df['date & time of connection'].dt.strftime('%d/%m/%Y %H:%M:%S')
print (df.head()) 

In [193]: %%timeit
     ...: df['date & time of connection']=pd.to_datetime(df['date & time of connection'])
     ...: df1 = df.groupby(by=df['date & time of connection'].dt.date).count()
     ...: 
539 ms ± 45.9 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

In [194]: %%timeit
     ...: df1 = (pd.to_datetime(df['date & time of connection'])
     ...:        .dt.floor('d')
     ...:        .value_counts()
     ...:        .rename_axis('date')
     ...:        .reset_index(name='count'))
     ...: 
12.4 ms ± 350 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

In [195]: %%timeit
     ...: s = pd.to_datetime(df['date & time of connection'])
     ...: df2 = s.groupby(s.dt.floor('d')).size().reset_index(name='count')
     ...: 
17.7 ms ± 140 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

33

确保你的列是日期格式。

df['date & time of connection']=pd.to_datetime(df['date & time of connection'])

然后您可以按日期分组数据并进行计数:

df.groupby(by=df['date & time of connection'].dt.date).count()
Out[10]: 
                           date & time of connection
date & time of connection                           
2017-06-19                                         3
2017-06-20                                         2
2017-06-21                                         5
2017-06-22                                         3
2017-06-23                                         6

7
使用.dt.date要比上面使用floor函数更加简洁优雅。 - ijoseph
为了使输出结果更加美观,最好只显示datecount两列。如果df有多个列,该代码将导致额外的列出现,这对于演示来说并不那么美观! - Pedram

12

嘿,我发现用重采样来做这件事情很简单。

# Set the date column as index column.
df = df.set_index('your_date_column')

# Make counts
df_counts = df.your_date_column.resample('D').count() 
虽然您的列名很长且包含空格,这让我有些不舒服。我会使用破折号代替空格。

尽管您的列名较长并含有空格,这使我感到有些不舒服。我会建议使用破折号代替空格。


4
不需要将“日期列”作为“索引”。您可以使用“on”参数:resample('D',on='your_date_column') - Cornelius Roemer

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接