【问题标题】:Faster For Loop to Manipulate Data in Pandas更快的 For 循环在 Pandas 中处理数据
【发布时间】:2017-01-19 23:55:03
【问题描述】:

我正在使用形状为 ~(100000, 50) 的 pandas 数据框,虽然我可以实现所需的数据格式和操作,但我发现我的代码运行时间比预期的要长(3-10 分钟),具体取决于具体任务,包括:

  1. 组合不同列中的字​​符串
  2. 将函数应用于数据框系列中的每个实例
  3. 检查值是否包含在单独的列表或 numpy 数组中

我将来会有更大的数据帧,并希望确保我使用适当的编码方法来避免很长的处理时间。我发现我的 for 循环耗时最长。我尽量避免使用列表推导和系列运算符(例如df.loc[:,'C'] = df.A + df.B)的for 循环,但在某些情况下,我需要使用嵌套的for 循环执行更复杂/涉及的操作。例如,下面遍历数据框的系列history(一系列列表),然后遍历每个list中的每个项目:

for row in DF.iterrows():

    removelist = []

    for i in xrange(0, len(row[1]['history'])-1):
        if ((row[1]['history'][i]['title'] == row[1]['history'][i+1]['title']) & 
            (row[1]['history'][i]['dept'] == row[1]['history'][i+1]['dept']) & 
            (row[1]['history'][i]['office'] == row[1]['history'][i+1]['office']) & 
            (row[1]['history'][i]['employment'] == row[1]['history'][i+1]['employment'])):
                removelist.append(i)

    newlist = [v for i, v in enumerate(row[1]['history']) if i not in removelist]

我知道列表推导可以容纳嵌套的 for 循环,但上面的内容在列表推导中看起来确实很麻烦。

我的问题:我可以使用哪些其他技术来实现与 for 循环相同的功能,并且处理时间更短?在遍历包含列表的系列时,我应该使用嵌套 for 循环以外的其他技术吗?

【问题讨论】:

    标签: python pandas numpy


    【解决方案1】:

    那么您在这里似乎有一个数据框,其中每行的历史条目都包含一个字典列表?喜欢:

    import pandas as pd
    john_history = [{'title': 'a', 'dept': 'cs'}, {'title': 'cj', 'dept': 'sales'}]
    john_history
    jill_history = [{'title': 'boss', 'dept': 'cs'}, {'title': 'boss', 'dept': 'cs'}, {'title': 'junior', 'dept': 'cs'}]
    jill_history
    df = pd.DataFrame({'history': [john_history, jill_history], 
        'firstname': ['john', 'jill']})
    

    我会重组您的数据,以便您在结构的底层使用 pandas 结构,例如DataFrames 的字典,其中每个 DataFrame 都是历史记录(我不认为 Panel 在这里工作,因为 DataFrames 可能有不同的长度):

    john_history = pd.DataFrame({'title': ['a', 'cj'], 'dept': ['cs', 'sales']})
    john_history['name'] = 'john'
    jill_history = pd.DataFrame({'title': ['boss', 'boss', 'junior'], 'dept': ['cs', 'cs', 'cs']})
    jill_history['name'] = 'jill'
    people = pd.concat([john_history, jill_history])
    

    然后您可以使用 groupby 处理它们,例如:

    people.groupby('name').apply(pd.DataFrame.drop_duplicates)
    

    一般来说,如果您在 pandas/numpy 中找不到您想要的功能,您应该会发现使用 pandas 原语创建它而不是迭代数据帧会更快。例如,要重新创建上面的逻辑,首先创建一个新的数据框,它是第一个移动的数据框:

    df2 = df.shift()
    

    现在您可以通过比较数据框的内容来创建选择,只保留不同的内容并使用它来过滤数据框:

    selection_array = (df.history == df2.history) & (df.title == df2.title)
    unduplicated_consecutive = df[~selection_array]
    print(unduplicated_consecutive)
      history  id title
    0       a   1     x
    1       b   2     y
    # or in one line:
    df[~((df.history == df2.history) & (df.title == df2.title))]
    # or:
    df[(df.history != df2.history) | (df.title != df2.title)]
    

    所以把这个放到groupby中:

    def drop_consecutive_duplicates(df):
        df2 = df.shift()
        return df.drop(df[(df.dept == df2.dept) & (df.title == df2.title)].index)
    
    people.groupby('name').apply(drop_consecutive_duplicates)
    

    【讨论】:

    • 不一定要删除重复项 - 但是,是的,根据某些逻辑删除。任何关于快速迭代包含列表项的数据框系列的 cmets?感谢之前的cmets。
    • 所以你想要一个框架的行并且每一行在每一列中都包含一个列表?我已经修改了我的答案,以展示如何使用 pandas 数据结构来做到这一点。
    猜你喜欢
    • 2020-09-25
    • 2022-01-12
    • 2021-08-12
    • 1970-01-01
    • 2015-06-17
    • 2021-03-20
    • 2019-12-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多