Суммируйте столбец, если значения в другом столбце уступают (без цикла for) - PullRequest
2 голосов
/ 01 ноября 2019

Фрейм данных

У меня есть фрейм данных со многими элементами.

Элементы идентифицируются кодом "Тип" и весом.

В последнем столбце указываетсяколичество.

|-|------|------|---------|
| | type |weight|quantity |
|-|------|------|---------|
|0|100010|   3  |  456    |
|1|100010|   1  |  159    |
|2|100010|   5  |  735    |
|3|100024|   3  |  153    |
|4|100024|   7  |  175    |
|5|100024|   1  |  759    |
|-|------|------|---------|

Правило совместимости

Данный элемент "A" "совместим" с другими элементами, если:

  • Это тот же тип
  • Вес других элементов равен или меньше веса элемента "A"

Ожидаемый результат

Я хочу добавить столбец "совместимколичество »рассчитывается для каждой строки, сколько элементов совместимы.

|-|------|------|---------|---------------------|
| | type |weight|quantity | compatible quantity |
|-|------|------|---------|---------------------|
|0|100010|   3  |  456    |        615          | 456 + 159
|1|100010|   1  |  159    |        159          | 159 only (the lightest items)
|2|100010|   5  |  735    |       1350          | 735 + 159 + 456 (the heaviest)   
|3|100024|   3  |  153    |        912          | 153 + 759
|4|100024|   7  |  175    |       1087          | ...
|5|100024|   1  |  759    |        759          | ...
|-|------|------|---------|---------------------|

Я хочу избежать использования цикла For, чтобы получить этот результат. (массив данных огромен).

Мой код с использованием цикла For

import pandas as pd 

df = pd.DataFrame([[100010, 3, 456],[100010, 1, 159],[100010, 5, 735], [100024, 3, 153], [100024, 7, 175], [100024, 1, 759]],columns = ["type", "weight", "quantity"])

print(df)

for inc in range(df["type"].count()):

    the_type = df["type"].iloc[inc]
    the_weight = df["weight"].iloc[inc]
    the_quantity = df["quantity"].iloc[inc]

    df.at[inc,"quantity_compatible"] = df.loc[(df["type"] == the_type) & (df["weight"] <= the_weight),"quantity"].sum()

print(df)

Некоторые возможные идеи

  • Может ли "применить" или "преобразовать" быть полезным?
  • Можно ли это сделать с помощью loc внутри loc?

Ответы [ 2 ]

1 голос
/ 01 ноября 2019

Сначала отсортируйте значения по weight и type, затем выполните groupby для cumsum и, наконец, выполните слияние по индексу:

df = pd.DataFrame([[100010, 3, 456],[100010, 1, 159],[100010, 5, 735], [100024, 3, 153], [100024, 7, 175], [100024, 1, 759]],columns = ["type", "weight", "quantity"])

new_df = df.merge(df.sort_values(["type","weight"])
                  .groupby("type")["quantity"]
                  .cumsum(),left_index=True, right_index=True)

print (new_df)

#
     type  weight  quantity_x  quantity_y
0  100010       3         456         615
1  100010       1         159         159
2  100010       5         735        1350
3  100024       3         153         912
4  100024       7         175        1087
5  100024       1         759         759
0 голосов
/ 01 ноября 2019

Решение

Попробуйте это.

import pandas as pd
from io import StringIO

s = """
    type    weight  quantity
0   100010  3   456
1   100010  1   159
2   100010  5   735
3   100024  3   153
4   100024  7   175
5   100024  1   759
"""

def process_dataframe(df, sort_values_by_init_index = True):
    df2 = df.groupby(by=['type','weight']).sum().reset_index()
    df3 = df.groupby(by=['type','weight']).sum().groupby(level=[0], as_index=False)['quantity_compatible'].cumsum().reset_index()
    df2['quantity_compatible'] = df3['quantity_compatible'].tolist()
    if sort_values_by_init_index:
        df2 = df2.sort_values('index')
    #print(df2)
    df2 = df2.reset_index().drop(columns=['index'])

    return df2

df = pd.read_csv(StringIO(s), sep='\t')
df.drop(columns='Unnamed: 0', inplace=True)
df['quantity_compatible'] = df['quantity'].copy()
df = df.reset_index()

# custom function
process_dataframe(df)

Выход :
enter image description here

Ссылки

  1. Сброс пандИндекс по сериям для удаления мультииндексов
  2. Совокупная сумма Pandas groupby
  3. Pandas Groupby и сумма только в одном столбце
  4. https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.reindex.html#pandas.DataFrame.reindex
  5. https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.groupby.html
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...