【问题标题】:How can I convert an excel function that is shown below into a python pandas code?如何将下面显示的 excel 函数转换为 python pandas 代码?
【发布时间】:2020-06-27 10:51:59
【问题描述】:

我有这样的excel函数

=IF(B17="","",MIN(MAX(CEILING((B17-MIN(B$17:B$46))/((MAX(B$17:B$46)-MIN(B$17:B$46))/10),1),1),10))

输入:

Column1 output
512.96  10
307.41  3
413.76  7
323.65  4
376.84  5
368.79  5
367.77  5
345.65  4

可以分解如下

ceiling((min-max)/10, 1)
max(ceiling, 1)
min(max,10)

我的代码运行到天花板功能如下

def point_10_conversion(new_df):
    g = ((new_df.sub(new_df.min(axis=0))) / ((new_df.max(axis=0)) - (new_df.min(axis=0))))/10
    f = np.around(g.astype(np.double), 3)
    ceil = np.ceil(f)
    print(ceil)

有人能帮忙把这个excel函数转换成pandas或python代码吗?我正在使用数据框进行计算。

提前谢谢你!!

【问题讨论】:

  • 请与预期的输出分享一些数据stackoverflow.com/questions/20109391/…
  • @sammywemmy,我也更新了问题
  • @dumb_coder 能否将其作为文本放入代码块以及与该输入关联的输出中?这样人们就可以复制/粘贴到他们的解释器中去实际尝试一些东西......
  • 谢谢,B$17:B$46 是什么 - 我们是否拥有所有必要的信息来实际计算此处仅给出 column1 的输出? (并且将您想要的输出视为单个值,或者显示 column2 以及值应该是什么......)

标签: python excel pandas numpy


【解决方案1】:

有一种方法可以翻译问题中提出的函数,而不必自己编写 Python。

PyCel、Formulas、xlcalculator 和 Koala 等库使用 AST 将 Excel 公式转换为 Python。

我是 xlcalculator 的项目所有者,所以我将在演示中使用该库。也就是说,其他库完全能够胜任这项特定任务。每个图书馆都有不同的遗产,因此它们有不同的优势。

通常,上述库读取 Excel 文件,将公式转换为 Python,然后提供评估功能。 Xlcalculator 还可以解析特制的字典,这正是我在这里利用的。

from xlcalculator import ModelCompiler
from xlcalculator import Model
from xlcalculator import Evaluator

input_dict = {
        "Sheet1!B16" : "Column1",
        "Sheet1!B17" : 512.96,
        "Sheet1!B18" : 307.41,
        "Sheet1!B19" : 413.76,
        "Sheet1!B20" : 323.65,
        "Sheet1!B21" : 376.84,
        "Sheet1!B22" : 368.79,
        "Sheet1!B23" : 367.77,
        "Sheet1!B24" : 345.65,

        "Sheet1!C16" : "OP results",
        "Sheet1!C17" : 10,
        "Sheet1!C18" : 3,
        "Sheet1!C19" : 7,
        "Sheet1!C20" : 4,
        "Sheet1!C21" : 5,
        "Sheet1!C22" : 5,
        "Sheet1!C23" : 5,
        "Sheet1!C24" : 4,

        "Sheet1!D16" : "Actual Output (Parfait)",
        "Sheet1!D17" : '=IF(B17="", "", MIN(MAX(CEILING((B17-MIN(B$17:B$46))/((MAX(B$17:B$46)-MIN(B$17:B$46))/10),1),1),10) )',
        "Sheet1!D18" : '=IF(B18="", "", MIN(MAX(CEILING((B18-MIN(B$17:B$46))/((MAX(B$17:B$46)-MIN(B$17:B$46))/10),1),1),10) )',
        "Sheet1!D19" : '=IF(B19="", "", MIN(MAX(CEILING((B19-MIN(B$17:B$46))/((MAX(B$17:B$46)-MIN(B$17:B$46))/10),1),1),10) )',
        "Sheet1!D20" : '=IF(B20="", "", MIN(MAX(CEILING((B20-MIN(B$17:B$46))/((MAX(B$17:B$46)-MIN(B$17:B$46))/10),1),1),10) )',
        "Sheet1!D21" : '=IF(B21="", "", MIN(MAX(CEILING((B21-MIN(B$17:B$46))/((MAX(B$17:B$46)-MIN(B$17:B$46))/10),1),1),10) )',
        "Sheet1!D22" : '=IF(B22="", "", MIN(MAX(CEILING((B22-MIN(B$17:B$46))/((MAX(B$17:B$46)-MIN(B$17:B$46))/10),1),1),10) )',
        "Sheet1!D23" : '=IF(B23="", "", MIN(MAX(CEILING((B23-MIN(B$17:B$46))/((MAX(B$17:B$46)-MIN(B$17:B$46))/10),1),1),10) )',
        "Sheet1!D24" : '=IF(B24="", "", MIN(MAX(CEILING((B24-MIN(B$17:B$46))/((MAX(B$17:B$46)-MIN(B$17:B$46))/10),1),1),10) )'
    }

compiler = ModelCompiler()
my_model = compiler.read_and_parse_dict(input_dict)
evaluator = Evaluator(my_model)

print(evaluator.evaluate("Sheet1!C16"))
print("Sheet1!C17", evaluator.evaluate("Sheet1!C17"))
print("Sheet1!C18", evaluator.evaluate("Sheet1!C18"))
print("Sheet1!C19", evaluator.evaluate("Sheet1!C19"))
print("Sheet1!C20", evaluator.evaluate("Sheet1!C20"))
print("Sheet1!C21", evaluator.evaluate("Sheet1!C21"))
print("Sheet1!C22", evaluator.evaluate("Sheet1!C22"))
print("Sheet1!C23", evaluator.evaluate("Sheet1!C23"))
print("Sheet1!C24", evaluator.evaluate("Sheet1!C24"))
print()
print(evaluator.evaluate("Sheet1!D16"))
print("Sheet1!D17", evaluator.evaluate("Sheet1!D17"))
print("Sheet1!D18", evaluator.evaluate("Sheet1!D18"))
print("Sheet1!D19", evaluator.evaluate("Sheet1!D19"))
print("Sheet1!D20", evaluator.evaluate("Sheet1!D20"))
print("Sheet1!D21", evaluator.evaluate("Sheet1!D21"))
print("Sheet1!D22", evaluator.evaluate("Sheet1!D22"))
print("Sheet1!D23", evaluator.evaluate("Sheet1!D23"))
print("Sheet1!D24", evaluator.evaluate("Sheet1!D24"))
>python stackoverflow.py
OP results
Sheet1!C17 10
Sheet1!C18 3
Sheet1!C19 7
Sheet1!C20 4
Sheet1!C21 5
Sheet1!C22 5
Sheet1!C23 5
Sheet1!C24 4

Actual Output (Parfait)
Sheet1!D17 10.0
Sheet1!D18 1
Sheet1!D19 6.0
Sheet1!D20 1.0
Sheet1!D21 4.0
Sheet1!D22 3.0
Sheet1!D23 3.0
Sheet1!D24 2.0

【讨论】:

    【解决方案2】:

    考虑将 Pandas Series 作为参数传递,以便返回与 Excel 公式由单个单元格运行以返回相同长度结果的结果相同长度的 Series。然后调用 Python 函数进行单列分配或使用 DataFrame.transform 进行选择列或所有列分配。

    def point_10_conversion(ser):
        g = (ser - ser.min()) / ((ser.max() - ser.min())/10)    
        res = pd.Series(np.ceil(g))
    
        # SERIES APPLY APPROACH (POSSIBLY SLOWER)
        # m_res = res.apply(lambda x: min(max(x, 1), 10))
    
        # NUMPY ARRAY APPROACH
        m_res = np.minimum(np.maximum(res, 1), 10)
    
        return m_res
    
    
    # ASSIGN A SINGLE COLUMN
    df['Output'] = point_10_conversion(df['Column1'])
    
    # ASSIGN SELECTED MULTIPLE COLUMNS (BY JOINING DFs)            
    df = pd.concat([df, (df.reindex(['Column1', 'Column2', 'Column3'], axis = 'columns')
                           .transform(point_10_conversion)
                           .set_axis(['Col1_Output', 'Col2_Output', 'Col3_Output'], 
                                     axis = 'columns', inplace = False)
                        )],
                   axis = 1)    
    
    # REPLACE ALL COLUMNS (ASSUMING ALL INT/FLOAT TYPES)
    df = df.transform(point_10_conversion)
    

    输出 (与与 OP 发布的数字不匹配的实际 Excel 公式输出相比)

    Excel

    Python

    • 分配单个列

          Column1  Output
      0   512.96    10.0
      1   307.41     1.0
      2   413.76     6.0
      3   323.65     1.0
      4   376.84     4.0
      5   368.79     3.0
      6   367.77     3.0
      7   345.65     2.0
      
    • 分配多列(使用随机生成的数据)

      np.random.seed(3162020)
      
      df = pd.DataFrame({'Column1': [512.96, 307.41, 413.76, 323.65, 376.84, 368.79, 367.77, 345.65],
                         'Column2': np.random.uniform(350, 500, 8),
                         'Column3': np.random.uniform(350, 500, 8)})
      
      # ASSIGN SELECTED MULTIPLE COLUMNS  
         Column1     Column2     Column3  Column1  Column2  Column3
      0   512.96  498.143814  465.920589     10.0     10.0      8.0
      1   307.41  405.430558  451.238911      1.0      4.0      7.0
      2   413.76  355.728386  362.713986      6.0      1.0      1.0
      3   323.65  498.231310  363.784559      1.0     10.0      1.0
      4   376.84  488.124593  420.322426      4.0     10.0      5.0
      5   368.79  469.047969  441.922624      3.0      8.0      7.0
      6   367.77  435.742375  492.355799      3.0      6.0     10.0
      7   345.65  474.028331  387.297520      2.0      9.0      2.0
      
      # REPLACE ALL COLUMNS (ASSUMING ALL INT/FLOAT TYPES)
         Column1  Column2  Column3
      0     10.0     10.0      8.0
      1      1.0      4.0      7.0
      2      6.0      1.0      1.0
      3      1.0     10.0      1.0
      4      4.0     10.0      5.0
      5      3.0      8.0      7.0
      6      3.0      6.0     10.0
      7      2.0      9.0      2.0
      

    Online Demo (点击顶部的运行)

    【讨论】:

      猜你喜欢
      • 2021-12-06
      • 1970-01-01
      • 1970-01-01
      • 2022-06-15
      • 1970-01-01
      • 2013-09-12
      • 1970-01-01
      • 2022-07-22
      • 2023-03-22
      相关资源
      最近更新 更多