代码之家  ›  专栏  ›  技术社区  ›  Ryan Honea

选择Pandas中的第一个Truthy列

  •  0
  • Ryan Honea  · 技术社区  · 3 年前

    我正在优化一些代码以提高速度,我理解这一点。在Pandas中应用并不是数据处理的最佳方法。我希望以某种方式优化此代码。

    假设你有两个这样的专栏

    设置一个 设置两个
    “Foo” ''
    '' '酒吧'
    “Foo” '酒吧'

    如果我想要一个application语句中两列中的第一个truthy值,我可以使用 df.apply(lambda x : x.Set_One or x.Set_Two)

    这将导致

    后果
    “Foo”
    '酒吧'
    “Foo”

    但随着数据集越来越大,速度会减慢。考虑到这是一个相当简单的比较,就不算多了。

    最好的解决方案是如果我能 result = df['Set_One'] or df['Set_Two'] 但级数的真值是模糊的。使用 & | 运算符不考虑truthiness(或处理字符串)。

    这种比较的最佳实践是什么?

    到目前为止,我只尝试了一个矢量化函数,它在功能上只返回第一个truthy值。

    def return_truthy(val1, val2):
        return val1 or val2
    
    vec_truthy = np.vectorize(return_truthy)
    
    vec_truthy(df['Set_One'], df['Set_Two'])
    

    使用此功能确实可以将速度提高约10倍,但看起来并不完全一样 优雅的

    2 回复  |  直到 3 年前
        1
  •  2
  •   jared    3 年前

    您可以使用 numpy.logical_or 作用

    import pandas as pd
    import numpy as np
    
    df = pd.DataFrame({"Set_One":["Foo", "", "Foo"], 
                       "Set_Two":["", "Bar", "Bar"]})
    print(np.logical_or(df["Set_One"], df["Set_Two"]))
    

    输出:

    0    Foo
    1    Bar
    2    Foo
    dtype: object
    
        2
  •  1
  •   Joshua Allen    3 年前

    贾里德上面说的是我认为最好的方式,我只是想补充一点,这也解决了问题中提到的速度问题。使用以下速度测试

    import pandas as pd
    import numpy as np
    import timeit
    
    # Create a large dataframe
    data = {
        "Set_One": ["foo", None, "foo"] * 100000,
        "Set_Two": [None, "bar", "bar"] * 100000,
    }
    df = pd.DataFrame(data)
    
    
    # Method 1: Using df.apply
    def method1():
        result = df.apply(lambda x: x.Set_One or x.Set_Two, axis=1)
    
    
    # Method 2: Using np.logical_or
    def method2():
        result = np.logical_or(df["Set_One"], df["Set_Two"])
    
    
    # Measure execution time for method 1
    time_method1 = timeit.timeit(method1, number=10)
    
    # Measure execution time for method 2
    time_method2 = timeit.timeit(method2, number=10)
    
    print("Time taken using df.apply(lambda x: x.Set_One or x.Set_Two):", time_method1)
    print(
        'Time taken using np.logical_or(df["Set_One"], df["Set_Two"]):', time_method2)
    
    times_faster = time_method1 / time_method2
    print("Method 2 is", times_faster, "times faster than method 1")
    

    我得到以下结果

    Time taken using df.apply(lambda x: x.Set_One or x.Set_Two): 20.352213299999903
    Time taken using np.logical_or(df["Set_One"], df["Set_Two"]): 0.05363929999998618
    Method 2 is 379.4272725409382 times faster than method 1