Python 从不同的大文件中洗牌数据的有效方法

Python 从不同的大文件中洗牌数据的有效方法,python,pandas,dataframe,Python,Pandas,Dataframe,例如,我拥有的是不同领域的df1和df2: df1 = pd.DataFrame({"question":["q1","q2"], "answer":["a1","a2"], "domain":"tech"}) df2 = pd.DataFrame({"question":["q3","q4"], "answer":["a3","a4"], "domain":"history"}) print(df1) question answer domain 0 q1 a1

例如,我拥有的是不同领域的
df1
df2

df1 = pd.DataFrame({"question":["q1","q2"], "answer":["a1","a2"], "domain":"tech"})
df2 = pd.DataFrame({"question":["q3","q4"], "answer":["a3","a4"], "domain":"history"})

print(df1)
  question answer domain
0       q1     a1   tech
1       q2     a2   tech

print(df2)
  question answer   domain
0       q3     a3  history
1       q4     a4  history
我想要的是无序数据:

print(shuffled1)
  question answer   domain
0       q3     a3  history
1       q1     a1     tech
print(shuffled2)
  question answer   domain
0       q2     a2     tech
1       q4     a4  history
在现实世界中,我有60多个来自不同领域的csv文件,它们具有相同的结构。每个文件有50k条记录。它们不能同时读入内存


我想做的是将这些文件输入到一个Bert模型中进行训练,但是如果该模型从“历史”域学习10公里步数的数据,然后再从“技术”域学习10公里步数的数据,那么该模型会做得不好因此,我想对文件中的数据进行洗牌,使多个域的数据均匀分布在每个文件中。

一个答案是逐个读取每个文件,并将行分布在新文件中。这样做,您将获得行数相似且“原始文件”比例相同的“无序文件”。当然,这在很大程度上取决于您需要什么样的无序文件

可以并行读取初始文件,但我们需要协调线程,使其不在同一文件中同时写入。我不会在这里描述这一点,因为我认为这对于这里需要的东西来说太多了。例如:

除了您拥有和/或想要的文件数量之外,下面的限制部分是洗牌。考虑到你的问题,因为它仅限于50k行的文件和机器学习,我认为下面的过程就足够了。50k*10的数组大约需要4MB,因此它可以完全加载到内存中,由
np.random.shuffle
洗牌。如果它大得多,则需要使用另一种方法,请参见

因此,程序可以是:

  • 对于原始文件1:
  • 读文件
  • 洗牌文件
  • 将文件分成
    N
    块(考虑到
    N
    大于行数)
  • 将块写入洗牌文件
  • 转到下一个文件并在1.1重新启动
  • 首先,我生成了50个文件,每个文件包含100000行25 Mb的数据:

    import pandas as pd
    import numpy as np
    
    for i in range(50):
        arr = np.random.randint(1000, size=(100000,10))
        with open(f'bigfile-{i}', 'w') as f: np.savetxt(f, arr, delimiter=',')
    
    这是一个粗略的代码,但它是有效的:

    originalFiles = [f'bigfile-{i}' for i in range(50)] # paths of your original files
    nbShuffled = len( originalFiles ) # number of shuffled files (you can choose)
    
    for i, file in enumerate( originalFiles ):
        # 1. Read the original file
        with open(file, 'r') as f: lines = f.readlines()
        # 2. Shuffle the file
        np.random.shuffle( lines )
        # 3. Estimate number of lines per block
        nbLines = len( lines )
        firstBlocks = int( np.floor( nbLines / nbShuffled ) )
        lastBlock = int( firstBlocks + nbLines % nbShuffled )
        blocks = [firstBlocks] * ( nbShuffled - 1 ) + [lastBlock]
        # 4. Write the blocks
        np.random.shuffle( blocks ) # avoid that the last block is always in the last shuffle file
        x = 0
        for b in range( nbShuffled ):
            with open( f'bigfile_shuffled-{i}', 'a' ) as f: f.writelines( lines[ x : x + blocks[b] ] )
            x += blocks[b]
    

    在我的计算机上运行(Linux 64位,32位RAM,16个CPU)需要13秒。

    为什么你说它们不能全部在内存中读取?如果你有100个文件,大小大约为5米,应该可以很好地存储在内存中。你的问题是什么?在飞行中洗牌?你能更好地解释你的目标吗?在我看来,你想创建一个考试,每个题目都从csv中随机抽取一个问题。@DavidS将数据洗牌并存储在不同的文件中。你为什么不简单地像这里一样并行读取文件,然后洗牌呢?