我正在对包含很多行的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
,行x
上i-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,因为在此之后没有可比较的内容。
答案 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)
我们屏蔽上一行X的值大于下一行X的行。
我们有条件地创建offset
列,其中的掩码为true,我们填充-1
否则为0
我们对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
注意,由于最后一行不能与下面的行进行比较,因此没有变化