Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/304.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 将熊猫中落在同一时间箱中的所有行分组_Python_Pandas_Time Series_Binning - Fatal编程技术网

Python 将熊猫中落在同一时间箱中的所有行分组

Python 将熊猫中落在同一时间箱中的所有行分组,python,pandas,time-series,binning,Python,Pandas,Time Series,Binning,我正在尝试定义在不同会话中使用了哪些应用程序。基本上,我将每5分钟定义为一个会话,并想知道数据集中有多少个移动会话。另外,我想知道在每个会话中启动了哪些应用程序。 我的数据框中的所有行都有时间戳。 以下是数据集中的一个示例: timestamp App 6773 2018-04-08 09:47:57.849 Chrome 6774 2018-04-08 09:48:17.573 YouTube 6775 2018-04-08 09:

我正在尝试定义在不同会话中使用了哪些应用程序。基本上,我将每5分钟定义为一个会话,并想知道数据集中有多少个移动会话。另外,我想知道在每个会话中启动了哪些应用程序。 我的数据框中的所有行都有时间戳。 以下是数据集中的一个示例:

        timestamp               App
6773    2018-04-08 09:47:57.849 Chrome
6774    2018-04-08 09:48:17.573 YouTube
6775    2018-04-08 09:48:28.538 Instagram
6776    2018-04-08 09:48:37.381 Maps
6777    2018-04-08 09:48:46.680 Netflix
6778    2018-04-08 09:48:56.672 Google Play Store
6779    2018-04-08 09:56:58.880 Google
6780    2018-04-08 09:57:25.461 DB Navigator
6781    2018-04-08 11:28:38.762 Google
6782    2018-04-08 12:58:31.455 Google
6783    2018-04-08 14:31:18.131 Google
6784    2018-04-08 14:31:29.209 Google
6785    2018-04-08 14:58:42.875 Google
6786    2018-04-08 18:18:04.757 Chrome
6787    2018-04-08 21:08:41.368 Google
6788    2018-04-11 10:53:10.744 Google
6789    2018-04-14 19:54:37.441 Google
6790    2018-04-14 19:54:59.833 Google
6791    2018-04-14 19:55:10.844 YouTube
6792    2018-04-14 19:55:34.486 Google
6793    2018-04-14 20:23:00.315 Google
6794    2018-04-15 08:23:44.873 Google
6795    2018-04-15 08:24:07.257 Google
这是所需的输出,其中添加了一个名为SessionID的新列,定义当前会话的id

        timestamp               App                     SessionID
6773    2018-04-08 09:47:57.849 Chrome                  1
6774    2018-04-08 09:48:17.573 YouTube                 1
6775    2018-04-08 09:48:28.538 Instagram               1
6776    2018-04-08 09:48:37.381 Maps                    1
6777    2018-04-08 09:48:46.680 Netflix                 1
6778    2018-04-08 09:48:56.672 Google Play Store       1
6779    2018-04-08 09:56:58.880 Google                  2
6780    2018-04-08 09:57:25.461 DB Navigator            2
6781    2018-04-08 11:28:38.762 Google                  3
6782    2018-04-08 12:58:31.455 Google                  4
6783    2018-04-08 14:31:18.131 Google                  5
6784    2018-04-08 14:31:29.209 Google                  5
6785    2018-04-08 14:58:42.875 Google                  6
6786    2018-04-08 18:18:04.757 Chrome                  7
6787    2018-04-08 21:08:41.368 Google                  8
6788    2018-04-11 10:53:10.744 Google                  9
6789    2018-04-14 19:54:37.441 Google                  10
6790    2018-04-14 19:54:59.833 Google                  10
6791    2018-04-14 19:55:10.844 YouTube                 10
6792    2018-04-14 19:55:34.486 Google                  10
6793    2018-04-14 20:23:00.315 Google                  11
6794    2018-04-15 08:23:44.873 Google                  12
6795    2018-04-15 08:24:07.257 Google                  12  

您可以四舍五入到最接近的5分钟,然后使用
factorize

fivemin=5*60*1000000000 
s=pd.to_datetime(((df.timestamp.astype(np.int64) // fivemin + 1 ) * fivemin))
df['new']=pd.factorize(s.astype(str))[0]+1
df
Out[66]: 
                    App               timestamp  new
6773             Chrome 2018-04-08 09:47:57.849    1
6774            YouTube 2018-04-08 09:48:17.573    1
6775          Instagram 2018-04-08 09:48:28.538    1
6776               Maps 2018-04-08 09:48:37.381    1
6777            Netflix 2018-04-08 09:48:46.680    1
6778  Google Play Store 2018-04-08 09:48:56.672    1
6779             Google 2018-04-08 09:56:58.880    2
6780       DB Navigator 2018-04-08 09:57:25.461    2
6781             Google 2018-04-08 11:28:38.762    3
6782             Google 2018-04-08 12:58:31.455    4
6783             Google 2018-04-08 14:31:18.131    5
6784             Google 2018-04-08 14:31:29.209    5
6785             Google 2018-04-08 14:58:42.875    6
6786             Chrome 2018-04-08 18:18:04.757    7
6787             Google 2018-04-08 21:08:41.368    8
6788             Google 2018-04-11 10:53:10.744    9
6789             Google 2018-04-14 19:54:37.441   10
6790             Google 2018-04-14 19:54:59.833   10
6791            YouTube 2018-04-14 19:55:10.844   11
6792             Google 2018-04-14 19:55:34.486   11
6793             Google 2018-04-14 20:23:00.315   12
6794             Google 2018-04-15 08:23:44.873   13
6795             Google 2018-04-15 08:24:07.257   13

您可以四舍五入到最接近的5分钟,然后使用
factorize

fivemin=5*60*1000000000 
s=pd.to_datetime(((df.timestamp.astype(np.int64) // fivemin + 1 ) * fivemin))
df['new']=pd.factorize(s.astype(str))[0]+1
df
Out[66]: 
                    App               timestamp  new
6773             Chrome 2018-04-08 09:47:57.849    1
6774            YouTube 2018-04-08 09:48:17.573    1
6775          Instagram 2018-04-08 09:48:28.538    1
6776               Maps 2018-04-08 09:48:37.381    1
6777            Netflix 2018-04-08 09:48:46.680    1
6778  Google Play Store 2018-04-08 09:48:56.672    1
6779             Google 2018-04-08 09:56:58.880    2
6780       DB Navigator 2018-04-08 09:57:25.461    2
6781             Google 2018-04-08 11:28:38.762    3
6782             Google 2018-04-08 12:58:31.455    4
6783             Google 2018-04-08 14:31:18.131    5
6784             Google 2018-04-08 14:31:29.209    5
6785             Google 2018-04-08 14:58:42.875    6
6786             Chrome 2018-04-08 18:18:04.757    7
6787             Google 2018-04-08 21:08:41.368    8
6788             Google 2018-04-11 10:53:10.744    9
6789             Google 2018-04-14 19:54:37.441   10
6790             Google 2018-04-14 19:54:59.833   10
6791            YouTube 2018-04-14 19:55:10.844   11
6792             Google 2018-04-14 19:55:34.486   11
6793             Google 2018-04-14 20:23:00.315   12
6794             Google 2018-04-15 08:23:44.873   13
6795             Google 2018-04-15 08:24:07.257   13

这是使用
np.unique的精简版

min5 = df['timestamp'].astype(np.int64)//(10**9*5*60)
df['SessionID'] = np.unique(min5, return_inverse=True)[1]+1
正如@Dav2357所指出的那样,你的第10组包括55.5%左右。我假设这是一个错误,但可以通过删除第一个值(如果这是您的基础)来更正:

说明:我们使用的事实是,我们可以使用
.astype(np.int64)
将datetime对象转换为纳秒。然后我们用
(10**9**5*60)
除法得到除数

除数是同一个5分钟插槽中的值相等的值

import pandas as pd
import numpy as np

data = '''\
2018-04-08T09:47:57.849,Chrome
2018-04-08T09:48:17.573,YouTube
2018-04-08T09:48:28.538,Instagram
2018-04-08T09:48:37.381,Maps
2018-04-08T09:48:46.680,Netflix
2018-04-08T09:48:56.672,Google Play Store
2018-04-08T09:56:58.880,Google
2018-04-08T09:57:25.461,DB Navigator
2018-04-08T11:28:38.762,Google
2018-04-08T12:58:31.455,Google
2018-04-08T14:31:18.131,Google
2018-04-08T14:31:29.209,Google
2018-04-08T14:58:42.875,Google
2018-04-08T18:18:04.757,Chrome
2018-04-08T21:08:41.368,Google
2018-04-11T10:53:10.744,Google
2018-04-14T19:54:37.441,Google
2018-04-14T19:54:59.833,Google
2018-04-14T19:55:10.844,YouTube
2018-04-14T19:55:34.486,Google
2018-04-14T20:23:00.315,Google
2018-04-15T08:23:44.873,Google
2018-04-15T08:24:07.257,Google'''

df = pd.read_csv(pd.compat.StringIO(data), names=['timestamp','App'], parse_dates=[0])
s = df['timestamp'].astype(np.int64)
df['SessionID'] = np.unique((s-s[0])//(10**9*5*60), return_inverse=True)[1]+1

print(df)
返回:

                 timestamp                App  SessionID
0  2018-04-08 09:47:57.849             Chrome          1
1  2018-04-08 09:48:17.573            YouTube          1
2  2018-04-08 09:48:28.538          Instagram          1
3  2018-04-08 09:48:37.381               Maps          1
4  2018-04-08 09:48:46.680            Netflix          1
5  2018-04-08 09:48:56.672  Google Play Store          1
6  2018-04-08 09:56:58.880             Google          2
7  2018-04-08 09:57:25.461       DB Navigator          2
8  2018-04-08 11:28:38.762             Google          3
9  2018-04-08 12:58:31.455             Google          4
10 2018-04-08 14:31:18.131             Google          5
11 2018-04-08 14:31:29.209             Google          5
12 2018-04-08 14:58:42.875             Google          6
13 2018-04-08 18:18:04.757             Chrome          7
14 2018-04-08 21:08:41.368             Google          8
15 2018-04-11 10:53:10.744             Google          9
16 2018-04-14 19:54:37.441             Google         10
17 2018-04-14 19:54:59.833             Google         10
18 2018-04-14 19:55:10.844            YouTube         10
19 2018-04-14 19:55:34.486             Google         10
20 2018-04-14 20:23:00.315             Google         11
21 2018-04-15 08:23:44.873             Google         12
22 2018-04-15 08:24:07.257             Google         12

时间比较:

1000 loops, best of 3: 962 µs per loop   <-- Anton-vBR 
1000 loops, best of 3: 1.34 ms per loop  <-- Dav2357 
1000 loops, best of 3: 1.43 ms per loop  <-- Wen

1000个循环,每个循环最好3:962µs这是使用
np的紧凑型版本。独特

min5 = df['timestamp'].astype(np.int64)//(10**9*5*60)
df['SessionID'] = np.unique(min5, return_inverse=True)[1]+1
正如@Dav2357所指出的那样,你的第10组包括55.5%左右。我假设这是一个错误,但可以通过删除第一个值(如果这是您的基础)来更正:

说明:我们使用的事实是,我们可以使用
.astype(np.int64)
将datetime对象转换为纳秒。然后我们用
(10**9**5*60)
除法得到除数

除数是同一个5分钟插槽中的值相等的值

import pandas as pd
import numpy as np

data = '''\
2018-04-08T09:47:57.849,Chrome
2018-04-08T09:48:17.573,YouTube
2018-04-08T09:48:28.538,Instagram
2018-04-08T09:48:37.381,Maps
2018-04-08T09:48:46.680,Netflix
2018-04-08T09:48:56.672,Google Play Store
2018-04-08T09:56:58.880,Google
2018-04-08T09:57:25.461,DB Navigator
2018-04-08T11:28:38.762,Google
2018-04-08T12:58:31.455,Google
2018-04-08T14:31:18.131,Google
2018-04-08T14:31:29.209,Google
2018-04-08T14:58:42.875,Google
2018-04-08T18:18:04.757,Chrome
2018-04-08T21:08:41.368,Google
2018-04-11T10:53:10.744,Google
2018-04-14T19:54:37.441,Google
2018-04-14T19:54:59.833,Google
2018-04-14T19:55:10.844,YouTube
2018-04-14T19:55:34.486,Google
2018-04-14T20:23:00.315,Google
2018-04-15T08:23:44.873,Google
2018-04-15T08:24:07.257,Google'''

df = pd.read_csv(pd.compat.StringIO(data), names=['timestamp','App'], parse_dates=[0])
s = df['timestamp'].astype(np.int64)
df['SessionID'] = np.unique((s-s[0])//(10**9*5*60), return_inverse=True)[1]+1

print(df)
返回:

                 timestamp                App  SessionID
0  2018-04-08 09:47:57.849             Chrome          1
1  2018-04-08 09:48:17.573            YouTube          1
2  2018-04-08 09:48:28.538          Instagram          1
3  2018-04-08 09:48:37.381               Maps          1
4  2018-04-08 09:48:46.680            Netflix          1
5  2018-04-08 09:48:56.672  Google Play Store          1
6  2018-04-08 09:56:58.880             Google          2
7  2018-04-08 09:57:25.461       DB Navigator          2
8  2018-04-08 11:28:38.762             Google          3
9  2018-04-08 12:58:31.455             Google          4
10 2018-04-08 14:31:18.131             Google          5
11 2018-04-08 14:31:29.209             Google          5
12 2018-04-08 14:58:42.875             Google          6
13 2018-04-08 18:18:04.757             Chrome          7
14 2018-04-08 21:08:41.368             Google          8
15 2018-04-11 10:53:10.744             Google          9
16 2018-04-14 19:54:37.441             Google         10
17 2018-04-14 19:54:59.833             Google         10
18 2018-04-14 19:55:10.844            YouTube         10
19 2018-04-14 19:55:34.486             Google         10
20 2018-04-14 20:23:00.315             Google         11
21 2018-04-15 08:23:44.873             Google         12
22 2018-04-15 08:24:07.257             Google         12

时间比较:

1000 loops, best of 3: 962 µs per loop   <-- Anton-vBR 
1000 loops, best of 3: 1.34 ms per loop  <-- Dav2357 
1000 loops, best of 3: 1.43 ms per loop  <-- Wen

1000个循环,每个循环最好3:962µs@Wen,@Anton vBR,如果我错了,请纠正我,但您的解决方案似乎返回了与OP发布的所需输出不同的6791 6792箱。我尝试了这种方法,这两种方法都是正确的:

start_t=df["Timestamp"].iloc[0]
df["ID"]=pd.factorize(df["Timestamp"].apply(lambda x: int((x-start_t).total_seconds()/60) // 5 ))[0]+1
输出:

                    App               Timestamp  ID
6773             Chrome 2018-04-08 09:47:57.849   1
6774            YouTube 2018-04-08 09:48:17.573   1
6775          Instagram 2018-04-08 09:48:28.538   1
6776               Maps 2018-04-08 09:48:37.381   1
6777            Netflix 2018-04-08 09:48:46.680   1
6778  Google Play Store 2018-04-08 09:48:56.672   1
6779             Google 2018-04-08 09:56:58.880   2
6780       DB Navigator 2018-04-08 09:57:25.461   2
6781             Google 2018-04-08 11:28:38.762   3
6782             Google 2018-04-08 12:58:31.455   4
6783             Google 2018-04-08 14:31:18.131   5
6784             Google 2018-04-08 14:31:29.209   5
6785             Google 2018-04-08 14:58:42.875   6
6786             Chrome 2018-04-08 18:18:04.757   7
6787             Google 2018-04-08 21:08:41.368   8
6788             Google 2018-04-11 10:53:10.744   9
6789             Google 2018-04-14 19:54:37.441  10
6790             Google 2018-04-14 19:54:59.833  10
6791            YouTube 2018-04-14 19:55:10.844  10
6792             Google 2018-04-14 19:55:34.486  10
6793             Google 2018-04-14 20:23:00.315  11
6794             Google 2018-04-15 08:23:44.873  12
6795             Google 2018-04-15 08:24:07.257  12

@Wen,@Anton vBR,如果我错了,请纠正我,但看起来您的解决方案返回的6791 6792的bin与OP发布的所需输出不同。我尝试了这种方法,它正确地处理了这两个问题:

start_t=df["Timestamp"].iloc[0]
df["ID"]=pd.factorize(df["Timestamp"].apply(lambda x: int((x-start_t).total_seconds()/60) // 5 ))[0]+1
输出:

                    App               Timestamp  ID
6773             Chrome 2018-04-08 09:47:57.849   1
6774            YouTube 2018-04-08 09:48:17.573   1
6775          Instagram 2018-04-08 09:48:28.538   1
6776               Maps 2018-04-08 09:48:37.381   1
6777            Netflix 2018-04-08 09:48:46.680   1
6778  Google Play Store 2018-04-08 09:48:56.672   1
6779             Google 2018-04-08 09:56:58.880   2
6780       DB Navigator 2018-04-08 09:57:25.461   2
6781             Google 2018-04-08 11:28:38.762   3
6782             Google 2018-04-08 12:58:31.455   4
6783             Google 2018-04-08 14:31:18.131   5
6784             Google 2018-04-08 14:31:29.209   5
6785             Google 2018-04-08 14:58:42.875   6
6786             Chrome 2018-04-08 18:18:04.757   7
6787             Google 2018-04-08 21:08:41.368   8
6788             Google 2018-04-11 10:53:10.744   9
6789             Google 2018-04-14 19:54:37.441  10
6790             Google 2018-04-14 19:54:59.833  10
6791            YouTube 2018-04-14 19:55:10.844  10
6792             Google 2018-04-14 19:55:34.486  10
6793             Google 2018-04-14 20:23:00.315  11
6794             Google 2018-04-15 08:23:44.873  12
6795             Google 2018-04-15 08:24:07.257  12


我删除了你上次的编辑,因为它使问题变得非常大。不过,这是一个很好的提问示例。@AntonvBR谢谢。我想让人们更容易复制数据。我删除了你上次的编辑,因为它使问题变得非常大。不过,这是一个很好的提问示例。@AntonvBR谢谢。我想让人们更容易复制这些数据。问题是这是一个错误还是故意的。我猜这是一个错误。我认为这两种方法的区别在于,在您的情况下,您考虑的是绝对时间,我使用的是第一条记录的经过时间,但不确定OP会选择哪一条。无论如何,注意得很好!您的解决方案也很好,但我会尽量避免使用
.apply()
。我把你的代码放在时间比较中,老实说,它没有那么慢!向上投票!我在我的回答中发布了一个替代解决方案,考虑了第一个值(与您一样),而没有使用
.apply()
。我在这里找到了这篇文章:。我很快就看完了。我认为它更贴切地描述了这个问题。问题是这是一个错误还是故意的。我猜这是一个错误。我认为这两种方法的区别在于,在您的情况下,您考虑的是绝对时间,我使用的是第一条记录的经过时间,但不确定OP会选择哪一条。无论如何,注意得很好!您的解决方案也很好,但我会尽量避免使用
.apply()
。我把你的代码放在时间比较中,老实说,它没有那么慢!向上投票!我在我的回答中发布了一个替代解决方案,考虑了第一个值(与您一样),而没有使用
.apply()
。我在这里找到了这篇文章:。我很快就看完了。我认为它更接近于描述这个问题。谢谢。您是否也可以添加另一种可能的会话方式?另一种创建会话的方法是:对于每个用户,如果在一个时间增量中发生两个后续操作,则少于5分钟的操作将分组到一个会话中。在超过5分钟的时间增量内完成的任何操作都将是新会话的开始。@Moh因此每个会话最多2次?不,没有最大值。只要动作在前一个动作的5分钟内完成,就应该在同一个会话中分组。谢谢。@Moh抱歉,但你可以像上次那样用数据解释这个问题。@Moh如果你能提出另一个可能更好的问题,因为这也为未来的用户服务。谢谢。您是否也可以添加另一种可能的会话方式?另一种创建会话的方法是:对于每个用户,如果在一个时间增量中发生两个后续操作,则少于5分钟的操作将分组到一个会话中。在超过5分钟的时间增量内完成的任何操作都将是新会话的开始。@Moh因此每个会话最多2次?不,没有最大值。只要动作在前一个动作的5分钟内完成,就应该在同一个会话中分组。谢谢。@Moh抱歉,但你可以用数据解释这一点,就像上次一样。@Moh如果你能提出另一个问题,可能会更好,因为这也为未来的用户服务。