【问题标题】:Is there a way to use a method/function as an expression for .loc() in pandas?有没有办法在熊猫中使用方法/函数作为 .loc() 的表达式?
【发布时间】:2021-07-24 22:08:22
【问题描述】:

我一直在疯狂地试图弄清楚这一点。我试图避免使用 df.iterrows() 来遍历数据帧的行,因为它非常耗时,而且 .loc() 比我所看到的更好。

我知道这行得通:

df = df.loc[df.number == 3, :]

这基本上会将 df 设置为“数字”列等于 3 的每一行。

但是,当我尝试这样的事情时出现错误:

df = df.loc[someFunction(df.number), :]

只要将所述行的“数字”值设置为参数,我想要获取 someFunction() 返回 True 的每一行。

由于某种原因,它传递了整个列(在此示例中为数据框的整个“数字”列),而不是像上一个示例那样在遍历行时传递行的值。

再一次,我知道我可以只使用 for 循环和 .iterrows(),但我正在处理大约 280,000 行,它只需要比我想要的更长的时间。还尝试过使用 lambda 函数。

【问题讨论】:

  • 我不清楚你在问什么......也许你想要 df.apply 它将通过每一行......但这可能不是做你想做的事情的最佳方式(我不太清楚你要做什么,或者为什么你不能像你在第一个例子中那样做索引)
  • @JoranBeasley 我也试过 df.appy。这是另一个示例:我有一个带有“数字”列的表。我有一个函数可以检查一个数字是否在 0 到 10 之间。现在,我想获取我的数据框中的所有行,其中“数字”中的数字在 0 到 10 之间,所以我使用我这样写的函数: df = df.loc[myFunction(df.number), :] 但是,它不是逐行传递一个值,而是将数据帧的整个“数字”列传递到“myFunction( df.number)" 调用,出于某种原因。这会导致一个问题。这有助于澄清一点吗?
  • @JoranBeasley 我希望这有助于澄清一点。我正在使用的数据比我的示例更复杂,这就是为什么我必须使用函数(使用 IP 和 IP 范围)。
  • 我怀疑你在追求错误的东西......有很多非常好的方法可以在熊猫中选择东西......逐行不是其中之一
  • 遗憾的是,我确实认为我需要逐行进行,因为在找到所需的行之后,我需要使用每一行的数据来计算新列的数据。

标签: python python-3.x pandas dataframe


【解决方案1】:

Apply 很慢 - 如果可以的话,尝试通过将序列作为参数将复杂的矢量化逻辑放入函数中:

import pandas as pd

df = pd.DataFrame()
df['a'] = [7, 6, 5, 4, 3, 2]
df['b'] = [1, 2, 3, 4, 5, 6]

def my_func(series1, series2):
  return (series2 > 3) | (series1 == series2)

df.loc[my_func(df.b, df.a), 'new_column_name'] = True

【讨论】:

    【解决方案2】:

    我认为这是你需要的:

    import pandas as pd
    
    
    df = pd.DataFrame({"number": [x for x in range(10)]})
    
    
    def someFunction(row):
        if row > 5:
            return True
        else:
            return False
    
    
    df = df.loc[df.number.apply(someFunction)]
    print(df)
    

    输出:

       number
    6       6
    7       7
    8       8
    9       9
    

    【讨论】:

    • 这帮助我完成了我想做的事情!谢谢,但是,正如其他人所说, apply() 似乎仍然需要很长时间。仍然感谢您的帮助。
    • 很高兴它有帮助。可能有比 apply 更好的解决方案,但我认为我们可能需要看看你的函数实际做了什么。
    【解决方案3】:

    您可以在 .loc 中使用匿名函数 x 指的是您要索引的数据框

    df.loc[lambda x: x.number > 5, :]
    
    

    【讨论】:

      【解决方案4】:

      我能想到的两个选项:

      1. 使用pandas apply() 方法和根据someFunction() 返回true 或false 的lambda 函数创建一个新列。然后,使用loc 过滤您刚刚创建的新列。

      2. 使用 for 循环和 df.itertuples(),因为它比 iterrows 快得多。请务必查看文档,因为 itertuples 的语法略有不同

      【讨论】:

        【解决方案5】:

        只要使用这样的东西就可以了

        df = pd.DataFrame()
        df['number'] = np.arange(10)
        display(df[df['number']>5])
        display(df[df['number']>2][df['number']<7])
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2020-07-04
          • 2019-12-26
          • 2017-04-28
          • 2019-12-10
          • 2021-03-28
          • 2021-02-04
          • 2021-07-03
          • 2019-12-10
          相关资源
          最近更新 更多