熊猫在两列上优化日期时间比较

时间:2018-11-23 11:49:08

标签: python pandas performance dataframe

如何优化以下操作:

df[(df.start <= x) & (df.end >= y)]

我尝试使用MultiIndex,但没有看到明显的加速。

df = df.set_index(['start', 'end'])
df[(df.index.get_level_values('start') <= end) & (discon_df.index.get_level_values('end') >= start)]

样本数据:

'<table border="1" class="dataframe">\n  <thead>\n    <tr style="text-align: right;">\n      <th></th>\n      <th>start</th>\n      <th>end</th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr>\n      <th>0</th>\n      <td>2018-11-13 10:28:30.304287</td>\n      <td>2018-11-13 10:46:28.663868</td>\n    </tr>\n    <tr>\n      <th>1</th>\n      <td>2018-11-13 12:27:32.226550</td>\n      <td>2018-11-13 13:09:02.723869</td>\n    </tr>\n    <tr>\n      <th>2</th>\n      <td>2018-11-13 13:29:29.981659</td>\n      <td>2018-11-13 13:54:01.138963</td>\n    </tr>\n    <tr>\n      <th>3</th>\n      <td>2018-11-13 14:30:49.380554</td>\n      <td>2018-11-13 14:48:50.627830</td>\n    </tr>\n    <tr>\n      <th>4</th>\n      <td>2018-11-13 14:59:26.799017</td>\n      <td>2018-11-13 15:24:00.453983</td>\n    </tr>\n    <tr>\n      <th>5</th>\n      <td>2018-11-13 16:30:16.824188</td>\n      <td>2018-11-13 16:48:35.346318</td>\n    </tr>\n    <tr>\n      <th>6</th>\n      <td>2018-11-13 17:15:25.486287</td>\n      <td>2018-11-13 17:59:30.774629</td>\n    </tr>\n    <tr>\n      <th>7</th>\n      <td>2018-11-13 18:27:41.915379</td>\n      <td>2018-11-13 18:47:26.528320</td>\n    </tr>\n    <tr>\n      <th>8</th>\n      <td>2018-11-13 19:28:12.835576</td>\n      <td>2018-11-13 19:52:15.448146</td>\n    </tr>\n    <tr>\n      <th>9</th>\n      <td>2018-11-13 20:41:41.210849</td>\n      <td>2018-11-13 21:07:52.249831</td>\n    </tr>\n    <tr>\n      <th>10</th>\n      <td>2018-11-13 21:11:23.529623</td>\n      <td>2018-11-13 21:42:10.106951</td>\n    </tr>\n  </tbody>\n</table>'

1 个答案:

答案 0 :(得分:1)

瓶颈是用于索引的布尔系列/数组的构建。

下降到NumPy似乎可以使性能得到合理的提高(〜2倍)。查看相关内容:pd.Timestamp versus np.datetime64: are they interchangeable for selected uses?

# boundaries for testing
mindt = pd.to_datetime('2016-01-01') 
maxdt = pd.to_datetime('2017-01-01')

x = ((df['start'] <= mindt) & (df['end'] >= maxdt)).values
y = (df['start'].values <= mindt.to_datetime64()) & (df['end'].values >= maxdt.to_datetime64())

# check results are the same
assert np.array_equal(x, y)

%timeit (df['start'].values <= mindt.to_datetime64()) & (df['end'].values >= maxdt.to_datetime64())
# 55.6 ms per loop

%timeit (df['start'] <= mindt) & (df['end'] >= maxdt)
# 108 ms per loop

设置

np.random.seed(0)

def random_dates(start, end, n):
    start_u = start.value//10**9
    end_u = end.value//10**9
    cols = ['start', 'end']
    df = pd.DataFrame({col: pd.to_datetime(np.random.randint(start_u, end_u, n), unit='s') for col in cols})
    df = pd.DataFrame(np.sort(df.values, axis=1), columns=cols)
    df[cols] = df[cols].apply(pd.to_datetime, errors='raise')
    return df

# construct a dataframe of random dates
df = random_dates(pd.to_datetime('2015-01-01'), pd.to_datetime('2018-01-01'), 10**7)