如果另一列中的值较差,则汇总一列(没有 for 循环)
Posted
技术标签:
【中文标题】如果另一列中的值较差,则汇总一列(没有 for 循环)【英文标题】:Summarize a column if values in another column are inferior (without for loop) 【发布时间】:2020-02-27 07:26:34 【问题描述】:数据框
我有很多项目的数据框。
项目由代码“类型”和重量标识。
最后一列表示数量。
|-|------|------|---------|
| | 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 吗?【问题讨论】:
【参考方案1】:首先按weight
和type
对值进行排序,然后对cumsum
执行groupby
,最后在索引上进行合并:
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
【讨论】:
【参考方案2】:解决方案
试试这个。
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)
输出:
参考文献
-
Pandas reset index on series to remove multiindex
Pandas groupby cumulative sum
Pandas Groupby and Sum Only One Column
https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.reindex.html#pandas.DataFrame.reindex
https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.groupby.html
【讨论】:
@floupinette 立即尝试。更新了解决方案以匹配预期的输出。以上是关于如果另一列中的值较差,则汇总一列(没有 for 循环)的主要内容,如果未能解决你的问题,请参考以下文章
检查一列中的值是不是存在于另一列中,如果存在,则将另一列中的值复制到新列中
Excel:如果在另一列中发现重复的单元格值,则突出显示绿色
在python中,我如何对一列中每个值与另一列中的值发生的次数(多少行)建立矩阵?