加快熊猫行动

时间:2019-07-04 13:04:59

标签: python pandas

我正在对包含很多行的pandas数据框执行操作,因此操作变得太慢。我想知道是否有一种方法可以对其进行优化。 假设我在数据框上有下一个数据:

         date        X
2019/5/1 10:00:00    1
2019/5/1 11:00:00    3
2019/5/1 12:00:00    5 
2019/5/1 13:00:00    2
2019/5/1 14:00:00    4 
2019/5/2 11:00:00    3
2019/5/2 12:00:00    2

我的代码要做的是检查对于行x上给定的i,行xi-1的值是否大于i+1行中的x,只要它们来自同一行。它会创建一个名为offset的新列,其中值是-1,其中前一条语句为true,否则为0,并且还会更新日期,将其减少1小时。代码:

for index, row in islice(df.iterrows(), 1, len(df.index)-1):
                if row.date.day == day:
                    if df.x[index-1] > df.x[index+1] or row.date.hour == 23:
                        df.offset[index] = -1
                        df.date[index] = df.date[index] - dt.timedelta(hours=1)
                else:
                    day = row.date.day

所需的输出将是这样:

       date          X    offset
2019/5/1 10:00:00    1     0
2019/5/1 11:00:00    3     0
2019/5/1 11:00:00    5     -1
2019/5/1 12:00:00    2     -1
2019/5/1 14:00:00    4     0      <---Note that on this row, the next one is from a new day, so we dont use on comparision
2019/5/2 11:00:00    3     0
2019/5/2 11:00:00    2     -1

*请注意时间上的差异。

此操作对一个包含约15K行和4列的文件花费大约10分钟的时间。我怎样才能加快速度?

谢谢

编辑:忘记提及。这些行必须是同一天的数据,否则,将无法进行比较。另外,如果该行是文件的最后一天还是一天的最后一天(23:00:00),则偏移量始终为-1,因为在此之后没有可比较的内容。

2 个答案:

答案 0 :(得分:2)

这是一种方法:

# date column to datatime format
df.date = pd.to_datetime(df.date)
# compare with shifted version, 2 samples away
s = df.X.gt(df.X.shift(-2)).shift().fillna(False)
# turn series of booleans to 0s and -1s
df['offset'] = s.mul(-1)
# last sample in offset to -1
df.loc[df.shape[0]-1, 'offset'] -= 1
# subtract 1h using the same offset column
df.date += pd.to_timedelta(df.offset, unit='h')

       date            X    offset
0 2019-05-01 10:00:00  1       0
1 2019-05-01 11:00:00  3       0
2 2019-05-01 11:00:00  5      -1
3 2019-05-01 12:00:00  2      -1
4 2019-05-01 14:00:00  3       0
5 2019-05-02 11:00:00  5       0
6 2019-05-02 11:00:00  4      -1

答案 1 :(得分:1)

  1. 我们屏蔽上一行X的值大于下一行X的行。

  2. 我们有条件地创建offset列,其中的掩码为true,我们填充-1否则为0

  3. 我们对date列执行相同的操作:如果掩码为True,我们减去1 hour

m = df['X'].shift() > df['X'].shift(-1)

df['offset'] = np.where(m, -1, 0)
df['date'] = np.where(m, df['date'] - pd.Timedelta(1, 'hour'), df['date'])

                 date  X  offset
0 2019-05-01 10:00:00  1       0
1 2019-05-01 11:00:00  3       0
2 2019-05-01 11:00:00  5      -1
3 2019-05-01 12:00:00  2      -1
4 2019-05-01 14:00:00  3       0
5 2019-05-02 11:00:00  5       0
6 2019-05-02 12:00:00  4       0

注意,由于最后一行不能与下面的行进行比较,因此没有变化