Python 将function/dict应用于选定列上数据帧中每个元素的最快方法

Python 将function/dict应用于选定列上数据帧中每个元素的最快方法,python,pandas,dictionary,apply,Python,Pandas,Dictionary,Apply,我想: 将数百个以制表符分隔的文件读入数据帧 根据FileNo 将函数应用于选定列上的每个元素 将所有数据帧追加并连接到单个帧中 示例文件: 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

我想:

  • 将数百个以制表符分隔的文件读入数据帧
  • 根据
    FileNo
  • 将函数应用于选定列上的每个元素
  • 将所有数据帧追加并连接到单个帧中
示例文件:

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)
目前完成读取和处理需要几个小时,当我需要增加要读取的文件数量时,我达到了内存限制

如果您能帮助我改进这段代码,我将不胜感激。特别是,

  • 这是应用函数的最佳/最快方法吗
  • 这是附加和关联许多数据帧的最佳/最快的方法吗

多谢各位

首先,我想你应该了解阅读csv与反转字符串所花费的时间

我可以看到一些东西可以加快程序的速度:

避免在列上循环

您可以使用和我的字典:

我认为这将大大提高性能

列出要避免的理解。追加

这可能会使语法变得有点麻烦,但效率可能会有微小的提高

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)]

谢谢你的评论!使用replace时,我担心它可能会受到传递替换覆盖的影响。dict={'a-b':'b-a','b-a':'a-b'}。当它在一个单元格上循环并看到“a-b”时,它会将其替换为“b-a”,然而,当它停留在同一个单元格中时,它可能会应用第二个键,该键会将单元格还原回其原始值。这就是为什么我认为我可以显式地使用列名并按列映射,而不是让replace迭代地应用。也许我错了?Re:追加部分:我想知道是否最好将文件连接成一个大文件,读入数据帧,然后处理(而不是读取每个文件、处理和连接)。计时:当只读取10个文件时,需要12.67(time.clock())无反转,和33.28。关于替换,这将不是一个问题。试试这个:pd.Series([1,2,3])。replace({1:2,2:3,3:4})。另外,在代码的注释部分,我展示了如何使用带有显式列名称的replace。奇怪的是,当我使用带有映射到列的原始for循环而不是replace时,它需要27.65.:/
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)]