Создание пользовательской накопленной суммы, которая рассчитывает последующие количества, учитывая список мест и их порядок - PullRequest
2 голосов
/ 21 февраля 2020

Я пытаюсь придумать какой-нибудь код, который по существу вычислит совокупное значение в местах под ним. Взятие кумулятивной суммы почти завершает это, но некоторые местоположения вносят вклад в ту же точку ниже по течению. Кроме того, большинство исходных точек (или начальных точек) не будут иметь каких-либо значений, способствующих им, и могут оставаться их начальными значениями в итоговом накопительном DataFrame.

Допустим, у меня есть следующий DataFrame для каждого сайта.

df = pd.DataFrame({
"Site 1": np.random.rand(10),
"Site 2": np.random.rand(10),
"Site 3": np.random.rand(10),
"Site 4": np.random.rand(10),
"Site 5": np.random.rand(10)})

У меня также есть таблица данных, в которой есть каждый сайт и соответствующий нисходящий компонент.

df_order = pd.DataFrame({
    "Site 1": Site 3,
    "Site 2": Site 3,
    "Site 3": Site 4,
    "Site 4": Site 5,
    "Site 5": None})

Я хочу сделать следующее:

1) Суммировать значения в восходящем направлении, чтобы получить кумулятивную сумму для соответствующего значения в нисходящем направлении. Например, сайт 1 и сайт 2 вносят вклад в ценность на сайте 3. Итак, я хочу добавить сайт 1, сайт 2 и сайт 3 вместе, чтобы получить совокупное значение на сайте 3.

2) Теперь что у меня есть это совокупное значение на сайте 3, я хочу сохранить это совокупное значение на сайте 3 в «df». Теперь я хочу распространить это значение на Сайт 4, сохранить его, обновив DataFrame, а затем перейти на Сайт 5.

Я могу получить значение close-i sh, используя cumsum, чтобы получить совокупное значение на каждом сайте , например:

df = df.cumsum(axis=1)

Однако это не учитывает того, что Сайт 1 и Сайт 2 вносят вклад в Сайт 3, а не друг в друга.

Что ж, я могу решить эту проблему вручную, используя:

df['Site 3'] = df.loc[:,'Site 1':'Site 3'].sum(axis = 1)
df['Site 4'] = df.loc[:,'Site 3':'Site 4'].sum(axis = 1)
df['Site 5'] = df.loc[:,'Site 4':'Site 5'].sum(axis = 1)

Однако мой фактический список сайтов гораздо более обширный, и ручной метод не учитывает автоматически предоставленный «df_order». Есть ли способ логически связать DataFrame "df_order" таким образом, чтобы он мог вычислить это автоматически? Я знаю, как сделать это вручную, как бы я расширил это, чтобы иметь возможность обрабатывать больший DataFrame и порядок сайтов?

Подумайте о большем DataFrame, потенциально до 50 сайтов, который выглядит следующим образом:

df_order = pd.DataFrame({
    "Site 1": Site 3,
    "Site 2": Site 3,
    "Site 3": Site 4,
    "Site 4": Site 5,
    "Site 5": Site 8,
    "Site 6": Site 8,
    "Site 7": Site 8,
    "Site 8": Site 9,
    "Site 9": None})

1 Ответ

1 голос
/ 21 февраля 2020

Вы можете использовать networkx для работы с отношениями. Сначала сделайте заказ DataFrame, например:

print(df_order)
   source  target
0  Site 1  Site 3
1  Site 2  Site 3
2  Site 3  Site 4
3  Site 4  Site 5
4  Site 5    None

Создайте ориентированный граф

import networkx as nx
G = nx.from_pandas_edgelist(df_order.dropna(), 
                            source='source', target='target', 
                            create_using=nx.DiGraph)

nx.draw(G, with_labels=True)

enter image description here


С этим ориентированным графом вы хотите получить все predecessors. Мы можем сделать это рекурсивно. (Ваш график должен быть направленным Acycli c График, в противном случае рекурсия может привести к проблемам)

def all_preds(G, target):
    preds=[target]
    for p in list(G.predecessors(target)):
        preds += all_preds(G, p)
    return preds

#Ex.
all_preds(G, 'Site 4')
['Site 4', 'Site 3', 'Site 1', 'Site 2']

И теперь мы можем создать ваши нижестоящие суммы, повторяющиеся по столбцам, выводимым этой функцией для всех ваших уникальных сайтов.

pd.concat([
    df[all_preds(G, target)].sum(1).rename(target)
    for target in df_order['source'].unique()
    ], axis=1)

Вывод с использованием np.random.seed(42)

     Site 1    Site 2    Site 3    Site 4    Site 5
0  0.374540  0.020584  1.006978  1.614522  1.736561
1  0.950714  0.969910  2.060118  2.230642  2.725819
2  0.731994  0.832443  1.856581  1.921633  1.956021
3  0.598658  0.212339  1.177359  2.126245  3.035565
4  0.156019  0.181825  0.793914  1.759546  2.018326
5  0.155995  0.183405  1.124575  1.932972  2.595495
6  0.058084  0.304242  0.562000  0.866613  1.178324
7  0.866176  0.524756  1.905167  2.002839  2.522907
8  0.601115  0.431945  1.625475  2.309708  2.856418
9  0.708073  0.291229  1.045752  1.485905  1.670759
...