簡體   English   中英

使用pandas從日志文件分析生成會話

[英]Session generation from log file analysis with pandas

我正在分析Apache日志文件,我已將其導入到pandas數據幀中。

'65 .55.52.118 - - [30 / May / 2013:06:58:52 -0600]“GET /detailedAddVen.php?refId=7954&uId=2802 HTTP / 1.1”200 4514“ - ”“Mozilla / 5.0(兼容; bingbot) /2.0; + http://www.bing.com/bingbot.htm )“'

我的數據幀:

在此輸入圖像描述

我想根據IP,代理和時差將其分組到會話中(如果持續時間大於30分鍾則應該是新會話)。

通過IP和Agent很容易對數據幀進行分組,但是如何檢查這個時間差?希望問題很清楚。

sessions = df.groupby(['IP', 'Agent']).size()

更新:df.index如下:

<class 'pandas.tseries.index.DatetimeIndex'>
[2013-05-30 06:00:41, ..., 2013-05-30 22:29:14]
Length: 31975, Freq: None, Timezone: None

我會使用shiftcumsum (這是一個簡單的例子,用數字代替次數 - 但它們的工作方式完全一樣):

In [11]: s = pd.Series([1., 1.1, 1.2, 2.7, 3.2, 3.8, 3.9])

In [12]: (s - s.shift(1) > 0.5).fillna(0).cumsum(skipna=False)  # *
Out[12]:
0    0
1    0
2    0
3    1
4    1
5    2
6    2
dtype: int64

* 需要skipna = False似乎是一個錯誤。

然后你可以在groupby中apply

In [21]: df = pd.DataFrame([[1.1, 1.7, 2.5, 2.6, 2.7, 3.4], list('AAABBB')]).T

In [22]: df.columns = ['time', 'ip']

In [23]: df
Out[23]:
  time ip
0  1.1  A
1  1.7  A
2  2.5  A
3  2.6  B
4  2.7  B
5  3.4  B

In [24]: g = df.groupby('ip')

In [25]: df['session_number'] = g['time'].apply(lambda s: (s - s.shift(1) > 0.5).fillna(0).cumsum(skipna=False))

In [26]: df
Out[26]:
  time ip  session_number
0  1.1  A               0
1  1.7  A               1
2  2.5  A               2
3  2.6  B               0
4  2.7  B               0
5  3.4  B               1

現在你可以組合'ip''session_number' (並分析每個會話)。

Andy Hayden的答案很可愛,簡潔,但是如果你有大量的用戶/ IP地址要分組,它會變得很慢。 這是另一種方法,它更加丑陋而且速度更快。

import pandas as pd
import numpy as np

sample = lambda x: np.random.choice(x, size=10000)
df = pd.DataFrame({'ip': sample(range(500)), 
                   'time': sample([1., 1.1, 1.2, 2.7, 3.2, 3.8, 3.9])})
max_diff = 0.5 # Max time difference

def method_1(df):
    df = df.sort_values('time')
    g = df.groupby('ip')
    df['session'] = g['time'].apply(
        lambda s: (s - s.shift(1) > max_diff).fillna(0).cumsum(skipna=False)
        )
    return df['session']


def method_2(df):
    # Sort by ip then time 
    df = df.sort_values(['ip', 'time'])

    # Get locations where the ip changes 
    ip_change = df.ip != df.ip.shift()
    time_or_ip_change = (df.time - df.time.shift() > max_diff) | ip_change
    df['session'] = time_or_ip_change.cumsum()

    # The cumsum operated over the whole series, so subtract out the first 
    # value for each IP
    df['tmp'] = 0
    df.loc[ip_change, 'tmp'] = df.loc[ip_change, 'session']
    df['tmp'] = np.maximum.accumulate(df.tmp)
    df['session'] = df.session - df.tmp

    # Delete the temporary column
    del df['tmp']
    return df['session']

r1 = method_1(df)
r2 = method_2(df)

assert (r1.sort_index() == r2.sort_index()).all()

%timeit method_1(df)
%timeit method_2(df)

400 ms ± 195 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
11.6 ms ± 2.04 ms per loop (mean ± std. dev. of 7 runs, 100 loops each)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM