【问题标题】:Replicate H Lookup Functionality in Python Pandas for Dataframe在 Python Pandas 中为 Dataframe 复制 H 查找功能
【发布时间】:2021-11-21 15:52:41
【问题描述】:

问题 - 如何最好地尝试解决问题,因为嵌套循环会减慢进程并且没有给出预期的结果

可以使用 Hlookup 在 Excel 中完成相同的操作,但由于它是重复性练习,我需要将其自动化

我有下面的查找表。

lookup = pd.DataFrame({'Fruit': ['Apple','Mango','Guava'],'Rate':[20,30,25],
               'Desc':['Apple rate is higher', 'Mango rate is higher', 'Guava rate is higher']})

我的目标是在我的输入数据中标记 desc,只要速率大于查找表中提到的速率

input_data = pd.DataFrame({'Id':[1,2,3,4,5], 'Apple':[24,27,30,15,18], 'Mango':[28,32,35,12,26],
                       'Guava':[20,23,34,56,23]})

预期输出数据样本 -

output_data = pd.DataFrame({'Id':[1,2,3,4,5], 'Apple':[24,27,30,15,18], 'Mango':[28,32,35,12,26],
                       'Guava':[20,23,34,56,23], 'Desc':['Apple rate is higher', 
                                                         'Apple rate is higher, Mango rate is higher',
                                                         'Apple rate is higher, Mango rate is higher, Guava rate is higher',
                                                         'Guava rate is higher', '']})

我尝试使用循环并创建了两个列表,它为我提供了要插入的索引和值。我很困惑如何进行下一步,这似乎是一个非常慢的方法,因为我有多个嵌套循环

for i in range(0,len(lookup)):
var1 = lookup['Fruit'][i]
value1 = lookup['Rate'][i]
desc1 = lookup['Desc'][i]

for j in range(0, len(input_data.columns)):
    var2 = input_data.columns[j]
    a=[]
    b=[]

    if var1 == var2:
        for k in range(0, len(input_data)):
            if input_data[var2][k] > value1:
                a.append(desc1)
                b.append(k)
        print (a)
        print (b)

我的代码输出

['苹果率更高', '苹果率更高', '苹果率更高'] [0, 1, 2]

['芒果率更高', '芒果率更高'] [1, 2]

['番石榴率较高', '番石榴率较高'] [2, 3]

【问题讨论】:

    标签: python pandas numpy loops if-statement


    【解决方案1】:

    你是如何做到你要求的

    import numpy as np
    import pandas as pd
    
    def desc_fruit_column(rate, desc, series):
        high_rate_mask = rate < series
        out = np.empty(series.shape, dtype=object)
        out[high_rate_mask] = desc + ", "
        out[~high_rate_mask] = ''
        return out
    
    desc_columns = [desc_fruit_column(rate, desc, input_data[col]) 
                    for rate,desc,col in zip(lookup.Rate, lookup.Desc, lookup.Fruit)]
    input_data['desc'] = np.sum(desc_columns, axis=0)
    input_data['desc'] = input_data['desc'].str.rstrip(", ")
    

    由于这是非常密集的代码,我将尝试解释一下。对于每一列 rate &lt; series 每当水果值超过比率时,都会为您提供一个真/假列表。然后out[high_rate_mask] = desc + ", " 为您提供每个 true 的相关文本,out[~high_rate_mask] = '' 在 false 的位置放置一个空字符串。 np.sum 对列求和,即将字符串放在一起,最后 .str.rstrip(", ") 删除了 ", "

    然后你得到

       Id  Apple  Mango  Guava                                               desc
    0   1     24     28     20                               Apple rate is higher
    1   2     27     32     23         Apple rate is higher, Mango rate is higher
    2   3     30     35     34  Apple rate is higher, Mango rate is higher, Gu...
    3   4     15     12     56                               Guava rate is higher
    4   5     18     26     23                                                   
    

    你应该问什么

    我是一个视觉型的人,我更喜欢为相关列着色而不是添加一些额外的文字。

    你可以这样做

    input_data.style.highlight_between(left=[np.nan,*lookup.Rate], axis=1, color="red")
    

    【讨论】:

    • 您提供的单行答案不容易阅读,也不是很好的pandas 做法,因为您使用了明确的for 循环
    • @gold_cy 你说得对,它有点密集,需要更多解释。不过,您对 for 循环的看法是不对的。使用具有少量固定迭代次数的 for 循环就可以了。如果您希望针对运行时优化代码,您可以单独保留 for 循环并尝试替换 .apply。但过早的优化是万恶之源。
    • 谢谢,我会记住问题的反馈。该解决方案运行良好
    • @gold_cy 实际上我改变了主意。你是对的,它很难阅读。我现在重写了。感谢您的评论。
    【解决方案2】:

    这可以使用pd.mergemeltgroupby 的组合来解决。

    tmp = pd.merge(
        input_data.melt(ignore_index=False) \
                  .reset_index(), 
        lookup, 
        how="inner", 
        left_on="variable", 
        right_on="Fruit"
    )
    
    vals = tmp.loc[tmp["value"] > tmp["Rate"]] \
              .groupby("index") \
              .agg({"Desc": ", ".join})
    
    pd.merge(input_data, vals, right_index=True, left_index=True, how="left")
    
       Id  Apple  Mango  Guava                                               Desc
    0   1     24     28     20                               Apple rate is higher
    1   2     27     32     23         Apple rate is higher, Mango rate is higher
    2   3     30     35     34  Apple rate is higher, Mango rate is higher, Gu...
    3   4     15     12     56                               Guava rate is higher
    4   5     18     26     23                                                NaN
    

    tmplookupinput_data 之间的连接,以便将它们放在一个 DataFrame 中,以便我们可以快速比较列之间的值并将Desc 附加到相关行。 vals 最终成为满足您描述的条件的行,然后我们将 groupby 保留在原始 input_data 表中的 index 并连接 Desc 列的值。最后,输出使用来自input_data 的原始index 作为连接条件连接vals 上的input_data。如果条件不满足,我们确保使用left 连接来保留原始行。

    【讨论】:

    • 谢谢,它工作得很好。
    猜你喜欢
    • 1970-01-01
    • 2018-03-14
    • 2019-10-09
    • 2021-02-23
    • 2019-10-20
    • 2018-03-19
    • 2021-11-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多