首页 > 解决方案 > 如何在熊猫的给定数据框中每分钟获取某个实体的计数?

问题描述

我有一个如下所示的数据框

data = [(datetime.datetime(2021, 2, 10, 7, 49, 7, 118658), u'12.100.90.10', u'100.100.12.1', u'LT_DOWN'),
       (datetime.datetime(2021, 2, 10, 7, 49, 14, 312273), u'12.100.90.10', u'100.100.12.1', u'LT_UP'),
       (datetime.datetime(2021, 2, 10, 7, 49, 21, 535932), u'12.100.90.10', u'100.100.12.1', u'LT_UP'),
       (datetime.datetime(2021, 2, 10, 7, 50, 28, 725961), u'12.100.90.10', u'100.100.12.1', u'PL_DOWN'),
       (datetime.datetime(2021, 2, 10, 7, 50, 32, 450853), u'10.100.80.10', u'10.55.10.1', u'PL_LOW'),
       (datetime.datetime(2021, 2, 10, 7, 51, 32, 450853), u'10.10.80.10', u'10.55.10.1', u'MA_HIGH'),
       (datetime.datetime(2021, 2, 10, 7, 52, 34, 264042), u'10.10.80.10', u'10.55.10.1', u'PL_DOWN')]

如您所见,每分钟记录一次数据。我刚刚在这里展示了完整数据的一部分。

这是在熊猫中加载它时的样子

                        date         start           end     type
0 2021-02-10 07:49:07.118658  12.100.90.10  100.100.12.1  LT_DOWN
1 2021-02-10 07:49:14.312273  12.100.90.10  100.100.12.1    LT_UP
2 2021-02-10 07:49:21.535932  12.100.90.10  100.100.12.1    LT_UP
3 2021-02-10 07:50:28.725961  12.100.90.10  100.100.12.1  PL_DOWN
4 2021-02-10 07:50:32.450853  10.100.80.10    10.55.10.1   PL_LOW
5 2021-02-10 07:51:32.450853   10.10.80.10    10.55.10.1  MA_HIGH
6 2021-02-10 07:52:34.264042   10.10.80.10    10.55.10.1  PL_DOWN

现在我想要的是两件事

首先,获取每分钟每个值的计数,此外,仅应考虑计数拆分值type的第一部分。_所以我的最终输出应该是这样的

              date LT PL  MA
0 2021-02-10 07:49 3  0   0
1 2021-02-10 07:50 0  2   0
2 2021-02-10 07:51 0  0   1
3 2021-02-10 07:52 0  1   0

其次将任何非零转换为True和零转换为False。所以最终输出看起来像

              date LT    PL     MA
0 2021-02-10 07:49 True  False  False
1 2021-02-10 07:50 False True   False
2 2021-02-10 07:51 False False  True
3 2021-02-10 07:52 False True   False

_现在关于第一部分,我可以通过执行类似这样的操作来找到总 Dataframe 上每个值的计数(在 的第一部分上拆分)

df = pd.DataFrame(data)
df.columns = ["date", "start", "end", "type"]
df = df.drop_duplicates()
issue = "LT"
df_check = df[df['type'].str.contains(issue)].groupby(['start', 'end']).size().to_frame('icount').reset_index()

但是我如何按分钟完成并将其映射到Trueand False

标签: pythonpandas

解决方案


在您提供的数据中,最后一项typeMA_DOWN,但在数据框和结果中PL_DOWN,我认为这是您的错误。我在这里考虑了数据框版本。

您可以pandas.DataFrame.resample使用pandas.get_dummies

>>> pd.get_dummies(df['type'].str.extract(r'(\w+)_', expand=False)
                   ).set_index(df['date']).resample('1T').sum()
                     LT  MA  PL
date                           
2021-02-10 07:49:00   3   0   0
2021-02-10 07:50:00   0   0   2
2021-02-10 07:51:00   0   1   0
2021-02-10 07:52:00   0   0   1

然后astype(bool)

>>> pd.get_dummies(df['type'].str.extract(r'(\w+)_', expand=False)
                   ).set_index(df['date']).resample('1T').sum().astype(bool)

                        LT     MA     PL
date                                    
2021-02-10 07:49:00   True  False  False
2021-02-10 07:50:00  False  False   True
2021-02-10 07:51:00  False   True  False
2021-02-10 07:52:00  False  False   True

根据您的意见,您可以使用pd.crosstab

>>> pd.crosstab(
       index=df['date'].dt.floor('1min'), 
       columns=[
           df['start'].add('-').add(df['end']).rename('star-end'), 
           df['type'].str.extract(r'(\w+)_', expand=False)
       ], 
       dropna=False
    )

start-end           10.10.80.10-10.55.10.1       10.100.80.10-10.55.10.1       12.100.90.10-100.100.12.1      
type                                    LT MA PL                      LT MA PL                        LT MA PL
date                                                                                                          
2021-02-10 07:49:00                      0  0  0                       0  0  0                         3  0  0
2021-02-10 07:50:00                      0  0  0                       0  0  1                         0  0  1
2021-02-10 07:51:00                      0  1  0                       0  0  0                         0  0  0
2021-02-10 07:52:00                      0  0  1                       0  0  0                         0  0  0

或者,

>>> pd.crosstab(
       index=df['date'].dt.floor('1min'), 
       columns=[
           df['start'], 
           df['end'], 
           df['type'].str.extract(r'(\w+)_', expand=False)
      ], 
      dropna=False
    )
 
start               10.10.80.10                          10.100.80.10                          12.100.90.10                         
end                  10.55.10.1       100.100.12.1         10.55.10.1       100.100.12.1         10.55.10.1       100.100.12.1      
type                         LT MA PL           LT MA PL           LT MA PL           LT MA PL           LT MA PL           LT MA PL
date                                                                                                                                
2021-02-10 07:49:00           0  0  0            0  0  0            0  0  0            0  0  0            0  0  0            3  0  0
2021-02-10 07:50:00           0  0  0            0  0  0            0  0  1            0  0  0            0  0  0            0  0  1
2021-02-10 07:51:00           0  1  0            0  0  0            0  0  0            0  0  0            0  0  0            0  0  0
2021-02-10 07:52:00           0  0  1            0  0  0            0  0  0            0  0  0            0  0  0            0  0  0

推荐阅读