我有大约400个txt文件,每个文件的大小在几MB到1 GB之间。这些txt文件包含长度分隔的数据。作为一个例子,考虑这两个txt文件(源文件中没有头):
File1.txt:
AB;12345A;400E;500C
CD;12345B;400E;500C
File2.txt:
EC;12345E;400E;500C
EF;12345E;400D;500E
(Once再次:虽然有分号,但这些文件不是“;“-separated它们是按长度分隔的,我用panda read_fwf读入的。)
我的第一个方法是读取每个txt文件,将其存储在 Dataframe 中,并将其附加/连接到一个大 Dataframe :
import pandas as pd
import glob
import csv
path = r'C:\folder\Test'
all_files = glob.glob(path + "\*.txt")
for filename in all_files:
print(filename)
col_lengths = {'Column1': range(0, 2),
'Column2': range(3, 9),
'Column3': range(10, 14),
'Column4': range(15, 19),
}
col_lengths = {k: set(v) for k, v in col_lengths.items()}
df = pd.read_fwf(filename, colspecs=[(min(x), max(x)+1) for x in col_lengths.values()], encoding='cp1252', header=None, names=col_lengths.keys(),
converters={'Column1':lambda x : str(x),
'Column2':lambda x : str(x),
'Column3':lambda x : str(x),
'Column4':lambda x : str(x),
}
)
li.append(df)
frame = pd.concat(li, axis=0, ignore_index=True)
frame.to_csv(r'C:\folder\Python test.csv', encoding='utf-8', index=False, sep=";", decimal=",", quoting=csv.QUOTE_NONE)
这段代码适用于示例文件,但不适用于我的原始数据,在那里我得到一个内存错误(“无法分配......用于具有形状......和数据类型对象的数组")
我的第二种方法是读入每个txt文件,将每个文件存储为csv文件,然后再次读取每个文件,并将其连接到一个大的 Dataframe 中:
import pandas as pd
import glob
import csv
import os
path = r'C:\folder\Test'
all_files = glob.glob(path + "\*.txt")
for filename in all_files:
col_lengths = {'Column1': range(0, 2),
'Column2': range(3, 9),
'Column3': range(10, 14),
'Column4': range(15, 19),
}
col_lengths = {k: set(v) for k, v in col_lengths.items()}
df = pd.read_fwf(filename, colspecs=[(min(x), max(x)+1) for x in col_lengths.values()], encoding='cp1252', header=None, names=col_lengths.keys(),
converters={'Column1':lambda x : str(x),
'Column2':lambda x : str(x),
'Column3':lambda x : str(x),
'Column4':lambda x : str(x),
}
)
# convert each txt file to a csv file
df.to_csv(os.path.join(path, os.path.splitext(os.path.basename(filename))[0] + '.' + "csv"), encoding='utf-8', index=False, sep=";", decimal=",", date_format='%d.%m.%Y', quoting=csv.QUOTE_MINIMAL)
# read in csv files and concatenate
path = r'C:\folder\Test'
all_files = glob.glob(os.path.join(path, "*.csv"))
dtypes= {"Column1": str, "Column2": str, "Column3": str, "Column4": str}
df = pd.concat((pd.read_csv(f, sep=";", encoding='utf-8', dtype=dtypes, decimal=",") for f in all_files), ignore_index=True)
df.to_csv(os.path.join(path,"File.csv"), encoding='utf-8', index=False, sep=";", decimal=",", quoting=csv.QUOTE_MINIMAL)
不幸的是,同样的问题再次出现:使用示例文件,但使用原始数据时再次出现内存错误。
问题总是出在pd.concat
上。我原以为第二种方法可能更好,但结果内存错误出现得更早。
作为第三种方法我尝试读入txt并导出为pickle文件,而不是csv,然后尝试连接这些pickle文件:
import pandas as pd
import glob
import csv
path = r'C:\folder\Test'
all_files = glob.glob(path + "\*.pkl")
li = []
for filename in all_files:
print(filename)
df = pd.read_pickle(filename)
li.append(df)
frame = pd.concat(li, axis=0, ignore_index=True)
frame.to_csv(r'C:\folder\Test\Test.csv', encoding='utf-8', index=False, sep=";", decimal=",", quoting=csv.QUOTE_MINIMAL)
它似乎运行得更快了,但很快又出现了内存错误。
在尝试其他数据格式如parquet,hdf 5或其他技术如dask之前,我的问题是:有没有一种更有效的方法让它运行,以某种方式让我绕过内存错误?
不幸的是,我的RAM大小被限制在16 GB。Windows 64 X和Python 64 X。当然操作系统和其他后台进程会占用一些可用的RAM。也许有一个选项可以改变系统参数并利用更多的RAM,因为Python Pandas没有使用全部的可能性,只是抛出了这个错误,但我并不是一个玩这样的系统参数的忠实粉丝,正如我认为根本原因可能是我如何处理这个问题的方式,我不能肯定地说,更多的RAM,甚至增加物理RAM大小到32 GB将解决这个问题。
(关于我上面的代码:我知道lambda x : str(x)
可以被简化为string,但无论如何,这并没有改变我的问题,仍然是内存错误问题。)
1条答案
按热度按时间qyyhg6bp1#
很有可能你根本不需要Pandas;只需读取每个文件并将它们流输出到一个文件:
然而,如果你想使用Pandas,你同样可以将 Dataframe 流传输到你事先打开的单个文件句柄中: