Я борюсь с суммой ряда после того, как уже сгруппировал фреймворк, и я надеялся, что кто-то может помочь мне с идеей. В основном, в приведенном ниже примере мне нужна сумма для каждого «Материала». Обычно материал «ABC» должен дать мне 2, а все остальные, поскольку они имеют только одну операцию знака, будут иметь такое же значение.
import numpy as np
import pandas as pd
df = pd.DataFrame({
"Material" : ["M-12", "H4-LAMPE", "M-12", "H4-LAMPE",
"ABC" , "H4-LAMPE", "ABC", "ABC"] ,
"Quantity" : [6, 1, 3, 5, 1, 1, 10, 9],
"TYPE": ["+", "-", "+", "-", "+", "-", "+", "-"]})
df.groupby(['Material', "Quantity"], as_index=False).count()
listX = []
for item in df["TYPE"]:
if item == "+":
listX.append(1)
elif item == "-":
listX.append(-1)
else:
pass
df["Sign"] = lista
df["MovementsQty"] = df["Quantity"]*df["Sign"]
#df = df.groupby(["Material", "TYPE", "Quantity1"]).sum()
df1 = df.groupby(["Material", "TYPE"]).sum()
df1.drop(columns=["Quantity", "Sign"], inplace=True)
print(df1)
Результат:
Желаемый результат:
Я попытался подвести итоги еще раз, рассмотреть по-другому, но пока мне это не удалось, и я думаю, что мне нужна помощь.
Большое спасибо за Вашу помощь
Вы на правильном пути. Я пытался улучшить ваш код. Просто используйте «Тип», чтобы определить и присвоить знак с помощью np.where
, выполните groupby
и sum
, а затем повторно вычислите столбец «Тип» на основе результата.
v = (df.assign(Quantity=np.where(df.TYPE == '+', df.Quantity, -df.Quantity))
.groupby('Material', as_index=False)[['Quantity']]
.sum())
v.insert(1, 'Type', np.where(np.sign(v.Quantity) == 1, '+', '-'))
print (v)
Material Type Quantity
0 ABC + 2
1 H4-LAMPE - -7
2 M-12 + 9
В качестве альтернативы вы можете сделать это с помощью двух вызовов groupby
:
i = df.query('TYPE == "+"').groupby('Material').Quantity.sum()
j = df.query('TYPE == "-"').groupby('Material').Quantity.sum()
# Find the union of the indexes.
idx = i.index.union(j.index)
# Reindex and subtract.
v = i.reindex(idx).fillna(0).sub(j.reindex(idx).fillna(0)).reset_index()
# Insert the Type column back into the result.
v.insert(1, 'Type', np.where(np.sign(v.Quantity) == 1, '+', '-'))
print(v)
Material Type Quantity
0 ABC + 2.0
1 H4-LAMPE - -7.0
2 M-12 + 9.0
Дагнаббит! Ты подтолкнул меня на это. df.assign(Quantity = np.where(df['TYPE'].eq('+'),df['Quantity'],-df['Quantity'])).groupby(['Material']).sum().pipe(lambda x: x.assign(TYPE = np.where(x.Quantity.lt(0),'-','+')))
У меня был классный однострочник с использованием pipe
.
@coldspeed: Большое спасибо!
Вот еще один вариант (хотя и довольно похожий на холодную скорость).
#Correct quantity with negative sign (-) according to TYPE
df.loc[df['TYPE'] == '-', 'Quantity'] *= -1
#Reconstruct df as sum of quantity to remove dups
df = df.groupby('Material')['Quantity'].sum().reset_index()
df['TYPE'] = np.where(df['Quantity'] < 0, '-', '+')
print(df)
Возврат:
Material Quantity TYPE
0 ABC 2 +
1 H4-LAMPE -7 -
2 M-12 9 +
map
и numpy.sign
Просто просуммируйте Quantity * TYPE
, а потом выясните знак.
d = {'+': 1, '-': -1}
r = dict(map(reversed, d.items())).get
q = df.Quantity
m = df.Material
t = df.TYPE
s = pd.Series((q * t.map(d)).values, m, name='MovementsQty').sum(level=0)
s.reset_index().assign(TYPE=lambda x: [*map(r, np.sign(x.MovementsQty))])
Material MovementsQty TYPE
0 M-12 9 +
1 H4-LAMPE -7 -
2 ABC 2 +
Предположительно, вам не нужен
Type
в желаемом результате, так как знак уже является частью количества чистых перемещений.