#python #arrays #pandas #performance #numpy
Вопрос:
Мне нужно как можно эффективнее назначить стек строк из pd.DataFrame по индексу матрице известного размера. Много, если индексы не будут существовать во фрейме данных, и эти строки должны быть заполнены NAN. Эта операция будет выполняться внутри цикла, повторяющегося по каждой строке в кадре данных, и должна выполняться как можно быстрее.
Короче говоря, я хочу ускорить следующую последовательность:
# DF to iterate over
df = pd.DataFrame({'a': [1,2,3,4], 'b': [2,4,6,8], 'c': [3,6,9,12]})
# (Relative) DF indices to return if possible
indices = [-2, 0, 2, 4]
len_df = len(df)
len_indices = len(indices)
len_cols = len(df.columns)
values = np.zeros((len_df, len_indices, len_cols))
for i in range(len_df):
for j, n in enumerate(indices):
idx = i n
try:
assert idx > 0 # avoid wrapping around
values[i, j] = df.iloc[idx]
except:
values[i, j] = np.nan
values
ВОЗВРАТ
[[[nan, nan, nan],
[ 1, 2, 3],
[ 3, 6, 9],
[nan, nan, nan]],
[[nan, nan, nan],
[ 2, 4, 6],
[ 4, 8, 12],
[nan, nan, nan]],
[[ 1, 2, 3],
[ 3, 6, 9],
[nan, nan, nan],
[nan, nan, nan]],
[[ 2, 4, 6],
[ 4, 8, 12],
[nan, nan, nan],
[nan, nan, nan]]]
По желанию, но довольно медленно. Есть какие-нибудь предложения?
По желанию
Комментарии:
1. больше похоже на то, что выиграло бы от numpy, чем от панд
Ответ №1:
Вот решение, которое создает таблицу поиска:
# repeat indices into new dimension
rep_ids = np.tile(indices, (len(df), 1))
# add row index to the tiled ids
range_ids = rep_ids np.arange(len(df))[:, np.newaxis]
# check which ids make a valid lookup in the df
# TODO: do you really mean > 0 here in the original code, not >= 0?
valid_test = (range_ids > 0) amp; (range_ids < len(df))
# lookup table, using 0 for invalid ids (will be overwritten later)
lookup_ids = np.where(valid_test, range_ids, 0)
# lookup all values
values = df.values[lookup_ids].astype(np.float64)
# set the invalids to nan
values[~valid_test] = np.nan