使用.iterrows()更加简洁地遍历pandas数据帧中的行,并在特定值之间跟踪行。

4

我有一个Python 2.7中的pandas数据框,我想要遍历行并获取两种事件之间的时间以及在此期间发生的其他类型事件的计数(在给定条件下)。

我的数据是一个pandas.DataFrame,看起来像这样:

     Time  Var1  EvntType  Var2
0    15    1     2         17
1    19    1     1         45
2    21    6     2         43
3    23    3     2         65
4    25    0     2         76 #this one should be skipped
5    26    2     2         35
6    28    3     2         25
7    31    5     1         16
8    33    1     2         25
9    36    5     1         36
10   39    1     2         21

我希望忽略那些 Var1 等于 0 的行,并计算事件类型 1 和类型 2(除了在类型 1 事件之间的 Var1 == 0)之间的时间差。所以在上述情况下:

Start_time: 19, Time_inbetween: 12, Event_count: 4
Start_time: 31, Time_inbetween: 5, Event_count: 1

我是通过以下方式进行的:

i=0
eventCounter = 0
lastStartTime = 0
length = data[data['EvntType']==1].shape[0]
results = np.zeros((length,3),dtype=int)
for row in data[data['Var1'] > 0].iterrows():
    myRow = row[1]
    if myRow['EvntType'] == 1:
        results[i,0] = lastStartTime
        results[i,1] = myRow['Time'] - lastStartTime
        results[i,2] = eventCounter
        lastStartTime = myRow['Time']
        eventCounter = 0
        i += 1
    else:
        eventCounter += 1

这使我得到了期望的结果:
>>> results[1:]
array([[19, 12,  4],
       [31,  5,  1]])

但这种方法似乎很绕弯并且在处理大型数据集时需要很长时间。我该如何改进这个过程呢?

1个回答

5

您可以使用以下方法删除Var1等于0的行:

df = df.loc[df['Var1'] != 0]

接下来创建一个布尔掩码,当 EvntType 为1时为True:

mask = df['EvntType']==1
# 0     False
# 1      True
# ...
# 9      True
# 10    False
# Name: EvntType, dtype: bool

查找与mask为真的行相关联的Time

times = df.loc[mask, 'Time']
# 1    19
# 7    31
# 9    36
# Name: Time, dtype: int64

并找到mask为真的序数索引:

idx = np.flatnonzero(mask)
# array([1, 6, 8])

start_timetimes[:-1]中的所有值。

In [56]: times[:-1]
Out[56]: 
1    19
7    31
Name: Time, dtype: int64

time_inbetween是时间的差异,即np.diff(times)

In [55]: np.diff(times)
Out[55]: array([12,  5])
< p >“event_count”是指“idx”之间的差值减1。< /p >
In [57]: np.diff(idx)-1
Out[57]: array([4, 1])

import numpy as np
import pandas as pd

df = pd.DataFrame({'EvntType': [2, 1, 2, 2, 2, 2, 2, 1, 2, 1, 2],
                   'Time': [15, 19, 21, 23, 25, 26, 28, 31, 33, 36, 39],
                   'Var1': [1, 1, 6, 3, 0, 2, 3, 5, 1, 5, 1],
                   'Var2': [17, 45, 43, 65, 76, 35, 25, 16, 25, 36, 21]})

# Remove rows where Var1 equals 0
df = df.loc[df['Var1'] != 0]

mask = df['EvntType']==1
times = df.loc[mask, 'Time']
idx = np.flatnonzero(mask)

result = pd.DataFrame(
    {'start_time': times[:-1],
     'time_inbetween': np.diff(times),
     'event_count': np.diff(idx)-1})

print(result)

产出
   event_count  start_time  time_inbetween
1            4          19              12
7            1          31               5

使用索引计数,如此简单优雅,非常感谢! - Swier
我通常使用 data = data[data['Var1']!=0].reset_index(drop=True) 来删除行并重置索引,这样你就可以直接使用索引,但是 np.flatnonzero() 也可以。 - Swier

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