如何在 python 中正确复制 excel sumproduct 函数?
How to replicate excel sumproduct function correctly in python?
我有一个像下面这样的数据框,我需要计算平均权重。在 excel 中,如果我使用 sumproduct 函数,我将得到 15.25 的结果。但是,当我使用以下代码时,它给了我 0。如何在代码中更正此问题?
import pandas as pd
df1 = { 'product1':['N/A'],
'product2':[15.25],
'p1 weight':[0],
'p2 weight':[4]}
df1=pd.DataFrame(df1)
df1.fillna(0,inplace=True)
cols_left = [c for c in df1.columns if 'product' in c]
cols_right = [c for c in df1.columns if 'weight' in c]
result = (df1[cols_left] * df1[cols_right]).sum(axis=1) / df1[cols_right].sum(axis=1)
df1['result'] = result
结果如下
请注意,我必须使用 cols_left 和 cols_right 方法,因为在我的实际工作情况下,我有 +100 列需要根据相应的列。
我没有像df1['result1'] = (df1['product1'] * df1['p1 weight'] + df1['product2'] * df1['p2 weight'] )/ df1['p1 weight'] + df1['p2 weight']
那样进行硬编码,而是在和积计算之前将cols_left和cols_right中的所有对应列分别分组。
非常感谢任何建议。
Pandas 支持(并强制)数据对齐。当您将一个操作应用于两个数据框时,该操作将应用于具有相同索引(名称)的行和列,而不是在相同的位置。要将操作应用于具有不同名称的一对列,您应该从中提取底层的 numpy 数组:
# Clean the NAs
import numpy as np
df1.replace("N/A", np.nan, inplace=True)
(df1[cols_left].fillna(0).values * df1[cols_right].values).sum() / df1[cols_right].sum(1)
#0 15.25
请注意 nan * 0
仍然是 nan
。您必须将 nan
s 转换为有限数字(例如,转换为 0s)以获得数字结果。
Numpy 方法:
df1 for below examples is defined in the last section of my answer
解决此问题的 numpy 方法是采用 np.nanprod
后跟 .sum()
。这个答案的灵感来自 this Whosebug solution.
A = df1.iloc[:,:2].values
B = df1.iloc[:,2:].values
num = np.nanprod(np.dstack((A,B)),2).sum(1)
den = df1.iloc[:,2:].sum(1)
df1['sumproduct'] = num/den
print(df1)
product1 product2 p1 weight p2 weight sumproduct
0 NaN 15.25 0 4 15.25
1 10.0 10.00 2 3 10.00
2 8.0 2.00 5 1 7.00
Pandas方法:
Pandas' 方式可能有点复杂,因为 pandas.DataFrame.dot
(这基本上是您想要的 sumproduct)不会给具有不同列名的数据帧带来很大的灵活性。但是,您可以将 pandas.groupby
与自定义石斑鱼一起使用来轻松完成产品。
尝试这种受 -
启发的方法
num_base_cols = 2 #number of columns per group
num_repeat = 2 #number of such groups
col_groups = np.tile(np.arange(num_base_cols), num_repeat) #[0,1,0,1] grouper
num = df1.groupby(col_groups, axis=1).prod().sum(1)
den = df1.iloc[:,2:].sum(1)
df1['sumproduct'] = num/den
print(df1)
product1 product2 p1 weight p2 weight sumproduct
0 NaN 15.25 0 4 15.25
1 10.0 10.00 2 3 10.00
2 8.0 2.00 5 1 7.00
PS - 我使用此数据框和一些添加的行来演示上述解决方案。此外,我使用适当的 np.nan
而不是 NAN
字符串来实现真实的虚拟输入。
import pandas as pd
import numpy as np #for adding proper Nans instead of strings
## added a few more rows for testing ##
#######################################
df1 = { 'product1':[np.nan,10,8],
'product2':[15.25,10,2],
'p1 weight':[0,2,5],
'p2 weight':[4,3,1]}
df1=pd.DataFrame(df1)
#######################################
我有一个像下面这样的数据框,我需要计算平均权重。在 excel 中,如果我使用 sumproduct 函数,我将得到 15.25 的结果。但是,当我使用以下代码时,它给了我 0。如何在代码中更正此问题?
import pandas as pd
df1 = { 'product1':['N/A'],
'product2':[15.25],
'p1 weight':[0],
'p2 weight':[4]}
df1=pd.DataFrame(df1)
df1.fillna(0,inplace=True)
cols_left = [c for c in df1.columns if 'product' in c]
cols_right = [c for c in df1.columns if 'weight' in c]
result = (df1[cols_left] * df1[cols_right]).sum(axis=1) / df1[cols_right].sum(axis=1)
df1['result'] = result
结果如下
请注意,我必须使用 cols_left 和 cols_right 方法,因为在我的实际工作情况下,我有 +100 列需要根据相应的列。
我没有像df1['result1'] = (df1['product1'] * df1['p1 weight'] + df1['product2'] * df1['p2 weight'] )/ df1['p1 weight'] + df1['p2 weight']
那样进行硬编码,而是在和积计算之前将cols_left和cols_right中的所有对应列分别分组。
非常感谢任何建议。
Pandas 支持(并强制)数据对齐。当您将一个操作应用于两个数据框时,该操作将应用于具有相同索引(名称)的行和列,而不是在相同的位置。要将操作应用于具有不同名称的一对列,您应该从中提取底层的 numpy 数组:
# Clean the NAs
import numpy as np
df1.replace("N/A", np.nan, inplace=True)
(df1[cols_left].fillna(0).values * df1[cols_right].values).sum() / df1[cols_right].sum(1)
#0 15.25
请注意 nan * 0
仍然是 nan
。您必须将 nan
s 转换为有限数字(例如,转换为 0s)以获得数字结果。
Numpy 方法:
df1 for below examples is defined in the last section of my answer
解决此问题的 numpy 方法是采用 np.nanprod
后跟 .sum()
。这个答案的灵感来自 this Whosebug solution.
A = df1.iloc[:,:2].values
B = df1.iloc[:,2:].values
num = np.nanprod(np.dstack((A,B)),2).sum(1)
den = df1.iloc[:,2:].sum(1)
df1['sumproduct'] = num/den
print(df1)
product1 product2 p1 weight p2 weight sumproduct
0 NaN 15.25 0 4 15.25
1 10.0 10.00 2 3 10.00
2 8.0 2.00 5 1 7.00
Pandas方法:
Pandas' 方式可能有点复杂,因为 pandas.DataFrame.dot
(这基本上是您想要的 sumproduct)不会给具有不同列名的数据帧带来很大的灵活性。但是,您可以将 pandas.groupby
与自定义石斑鱼一起使用来轻松完成产品。
尝试这种受
num_base_cols = 2 #number of columns per group
num_repeat = 2 #number of such groups
col_groups = np.tile(np.arange(num_base_cols), num_repeat) #[0,1,0,1] grouper
num = df1.groupby(col_groups, axis=1).prod().sum(1)
den = df1.iloc[:,2:].sum(1)
df1['sumproduct'] = num/den
print(df1)
product1 product2 p1 weight p2 weight sumproduct
0 NaN 15.25 0 4 15.25
1 10.0 10.00 2 3 10.00
2 8.0 2.00 5 1 7.00
PS - 我使用此数据框和一些添加的行来演示上述解决方案。此外,我使用适当的 np.nan
而不是 NAN
字符串来实现真实的虚拟输入。
import pandas as pd
import numpy as np #for adding proper Nans instead of strings
## added a few more rows for testing ##
#######################################
df1 = { 'product1':[np.nan,10,8],
'product2':[15.25,10,2],
'p1 weight':[0,2,5],
'p2 weight':[4,3,1]}
df1=pd.DataFrame(df1)
#######################################