【问题标题】:Fastest way to apply function/dict to every element in a pandas DataFrame on selected columns将函数/字典应用于选定列上 pandas DataFrame 中每个元素的最快方法
【发布时间】:2017-04-10 08:22:44
【问题描述】:

我想:

  • 将数百个制表符分隔文件读入 pandas DataFrame
  • 根据FileNo决定是否应用函数
  • 将函数应用于选定列上的每个元素
  • 将所有 DataFrame 附加并连接到单个帧中

示例文件:

ID    FileNo    Name    A1    A2    A3
1    0     John    a-b    b-a    a-a
2    0    Carol    b-b    a-b    a-b
[...]
500    0   Steve    a-a    b-b     a-b
501    0    Jack     b-a    b-a     a-b

每个文件的真实尺寸:2000x15000

功能:反转字符串。

flip_over = lambda x: x[::-1]
or
my_dict = {'a-b':'b-a', 'a-a':'a-a', 'b-b':'b-b', 'b-a':'a-b'}
map(my_dict)

我目前拥有的:

whether_to_flip = [7,15,23,36,48,85]
frames = []
base_path = "/home/user/file_"

for i in range(0, 100):
    path = base_path + str(i) + ".tsv"
    df = pd.read_csv(path, sep="\t", header=None)
    df['FileNo'] = str(i)
    if i in whether_to_flip:
          for j in range(3,6):
                 df[j] = df[j].map(my_dict)
    frames.append(df)

combined = pd.concat(frames, axis=0, ignore_index=True)

目前完成读取和处理需要几个小时,当我需要增加要读取的文件数量时,我达到了内存限制。

对于改进此代码的任何帮助,我将不胜感激。特别是,

  • 这是应用函数的最佳/最快方式吗?
  • 这是追加和连接许多 DataFrame 的最佳/最快方式吗?

谢谢。

【问题讨论】:

    标签: python pandas dictionary apply


    【解决方案1】:

    首先,我想您应该了解读取 csv 与反转字符串的时间相比您损失了多少时间。

    我可以看到一些可以加快程序速度的事情:

    避免列上的循环

    您可以使用replace 和my_dict:(ref)

    if i in whether_to_flip:
        df = df.replace(my_dict)
    #   df = df.replace({'A1' : my_dict, 'A2' : my_dict, 'A3' : my_dict)
    

    我认为这应该会大大提高性能。

    要避免使用 .append 的列表理解

    这会使语法变得更麻烦,但some 的效率提升很小

    def do_path(x):
        return base_path + str(i) + ".csv"  
    
    
    
    [ pd.read_csv(do_path(i), sep="\t", header=None).assign(FileNo = str(i)) if i not in whether_to_flip
      else pd.read_csv(do_path(i), sep="\t", header=None).assign(FileNo = str(i)).map(my_dict)
      for i in range(0, 100)]
    

    【讨论】:

    • 感谢您的评论!我担心使用替换是它可能会受到传递替换覆盖的影响。 dict = {'a-b': 'b-a', 'b-a':'a-b'}。当它遍历一个单元格并看到“a-b”时,它将用“b-a”替换它,但是,当它停留在同一个单元格中时,它可能会应用第二个键,这会将单元格恢复为其原始状态价值。这就是为什么我认为我可以明确地使用列名并按列映射而不是让替换迭代地应用。也许我错了?
    • Re: appending part: 我想知道是否最好将文件连接成一个大文件,将其读入 pandas 数据帧,然后处理它(而不是读取每个文件、处理和连接) )。
    • 计时:只读取10个文件时,不倒置需要12.67(time.clock()),倒置需要33.28。
    • 关于替换,这不是问题。试试这个:pd.Series([1,2,3]).replace({1 : 2, 2 : 3, 3 : 4})。此外,在代码的注释部分中,我展示了如何使用显式列名替换
    • 很奇怪,当我使用原始 for 循环并在列上映射而不是替换时,它需要 27.65。 ://
    猜你喜欢
    • 2018-07-06
    • 2017-12-09
    • 1970-01-01
    • 1970-01-01
    • 2019-07-29
    • 1970-01-01
    • 2014-09-24
    • 2017-01-21
    相关资源
    最近更新 更多