Контекст проблемы
Я запускаю моделирование дискретных событий, где в конце каждого события я сохраняю состояние системы в строке фрейма данных. У каждого прогона симуляции есть часы, которые определяют, какие события запускаются и когда, все симуляции имеют одинаковые начальные часы (0) и те же конечные часы (конец симуляции). но количество строк для фреймов данных может быть другим, потому что симуляция имеет несколько сточасти c компонентов. Затем столбец часов преобразуется в метку времени и используется в качестве индекса кадра данных.
Каждый раз, когда выполняется моделирование, рекомендуется запускать его много раз, а затем усреднять по всем репликам, делая это в этой настройке немного сложнее, потому что каждая симуляция создавала фрейм данных с разными индексами.
Предлагаемое решение
Пока это решение, которое я нашел:
# Auxiliary functions
def get_union_index(dfs):
index_union = dfs[0].index
for df in dfs[1:]:
index_union = index_union.union(df.index)
return pd.Series(index_union).drop_duplicates().reset_index(drop=True)
def interpolate(df, index, method='time'):
aux = df.astype(float)
aux = aux.reindex(index).fillna(method='ffill').fillna(method='bfill')
return aux
# Simulation
dfs = []
replicates = 30
seeds = list(range(40, 40 + replicates))
dfs = [simulate(seed=seed, **parameters) for seed in seeds]
# Main Code
union_index = get_union_index(dfs)
dfs_interpolates = [interpolate(df, union_index) for df in dfs]
df_concat = pd.concat(dfs_interpolates)
by_row_index = df_concat.groupby(df_concat.index)
# Averaging
df_means = by_row_index.mean()
df_std = by_row_index.std()
Пояснение
Сначала необходимо объединить все индексы, затем этот объединенный индекс используется для повторной индексации всех фреймов данных, а значения nan
заполняются с помощью интерполяции.
Вопросы
Есть ли собственная функция pandas, которая могла бы упростить это?
(Если не 1) Есть ли альтернативный способ напрямую объединить наборы данных, поскольку большинство индексов не пересекаются, union_index
имеет длину примерно len(df) * len(dfs)
, что на самом деле огромно.
В этом случае я использую ffill
, а затем bfill
, но решение должно позволять более общему методу interpolate
поддерживать различные и более сложные подходы. Основная проблема заключается в том, что, поскольку каждая строка является событием (до интерполяции), только несколько столбцов (иногда ни одного) изменяются в двух последовательных строках, что позволяет иметь несколько последовательных строк с одинаковыми значениями в нескольких столбцах и, таким образом, иметь много избыточных значений и даже больше после интерполяции (особенно для fill и bfill).
EDIT Добавить данные для воспроизведения и изменения вопроса 3
dfs
- это список из 3 фреймов данных следующим образом:
Then dfs_interpolates
is also a list of 3 DataFrames but this time the indexes are exactly the same, namely:
Finally the expected result should be a row-wise application of a function (mean, median, etc.) across the different dataframes in dfs_interpolates
. For the case of the mean the result should be:
введите описание изображения здесь