Интерполяция по разным фреймам данных с Pandas - PullRequest
1 голос
/ 06 августа 2020

Контекст проблемы

Я запускаю моделирование дискретных событий, где в конце каждого события я сохраняю состояние системы в строке фрейма данных. У каждого прогона симуляции есть часы, которые определяют, какие события запускаются и когда, все симуляции имеют одинаковые начальные часы (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 заполняются с помощью интерполяции.

Вопросы

  1. Есть ли собственная функция pandas, которая могла бы упростить это?

  2. (Если не 1) Есть ли альтернативный способ напрямую объединить наборы данных, поскольку большинство индексов не пересекаются, union_index имеет длину примерно len(df) * len(dfs), что на самом деле огромно.

  3. В этом случае я использую ffill, а затем bfill, но решение должно позволять более общему методу interpolate поддерживать различные и более сложные подходы. Основная проблема заключается в том, что, поскольку каждая строка является событием (до интерполяции), только несколько столбцов (иногда ни одного) изменяются в двух последовательных строках, что позволяет иметь несколько последовательных строк с одинаковыми значениями в нескольких столбцах и, таким образом, иметь много избыточных значений и даже больше после интерполяции (особенно для fill и bfill).

EDIT Добавить данные для воспроизведения и изменения вопроса 3

dfs - это список из 3 фреймов данных следующим образом: enter image description here

Then dfs_interpolates is also a list of 3 DataFrames but this time the indexes are exactly the same, namely:

enter image description here

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:

введите описание изображения здесь

...