我有相当大的 LZMA 压缩数据文件,我想使用 Pandas 读取这些文件以提取某些列的最小值和最大值。该文件是使用 grep -n
从在 MPI 下运行的程序的日志文件中生成的,因此包含多个 MPI 等级同时写入 stdout 的乱码行。
这个问题与 this one 非常相似,但我需要对每一列做同样的事情 3 次。我尝试了那里提供的各种答案都无济于事。
这是我目前得到的 Python 脚本:
import os # to check file existence
import sys # for argc, argv
import re # regex
import lzma as xz
import numpy as np
import pandas as pd
# Quick exit if file does not exist
if not os.path.exists(argv[1]):
help(); sys.exit( 'Error: cannot read file', argv[1] );
else:
# Define column names and columns to take
cols = [ 4, 7, 10 ];
colnames = [ 'm', 'n', 'k' ];
# Read file through LZMA decompressor
ifname = argv[1];
ifile = xz.open( ifname, 'rt' );
data = pd.read_csv( ifile, delim_whitespace=True, \
usecols=cols, names=colnames, \
error_bad_lines=False );
ifile.close();
### Insert filtering method here to transform data to data_clean
mdims = data_clean['m'].to_numpy();
mmin = np.amin(mdims);
mmax = np.amax(mdims);
ndims = data_clean['n'].to_numpy();
nmin = np.amin(ndims);
nmax = np.amax(ndims);
kdims = data_clean['k'].to_numpy();
kmin = np.amin(kdims);
kmax = np.amax(kdims);
# Display output
print( re.sub( ifname, '.xz', '' ), ':' );
print( 'M =', mmin, '-', mmax );
print( 'N =', nmin, '-', nmax );
print( 'K =', kmin, '-', kmax );
sys.exit(0);
Here 是您可以测试的两个数据文件。任何帮助将不胜感激。
答案 0 :(得分:1)
说到数据过滤,越早越好...
在这里,我将在加载时使用转换器将有问题的值替换为 NaN 。这样,过滤就只需要 dropna
:
def convert(x):
try:
return np.int64(x)
except ValueError:
return np.nan
...
data = pd.read_csv( ifile, delim_whitespace=True, \
usecols=cols, names=colnames, \
error_bad_lines=False, \
converters= {k: convert for k in colnames})
data_clean = data.dropna().astype('int64')
但实际上,尝试使用 csv 阅读器只是为时已晚。因为它不是真正的 csv 文件,而是包含如下行:
793883: zgemm: m = 51 n = 449 k = 2408
793884: zgemm: m = 51 n = 449 k = 2408
793885: zgemm: m = 51 n = 449 k = 2408
793886: zgemm: m = 51 n = 449 k = 2408
793887: zgemm: m = 51 n = 449 k = 2408
793888: zgemm: m = 51 n = 449 k = 2408
到目前为止一切顺利,问题是还包含像
这样的乱码3251002: ) into ( zgemm: m = 51 n = 449 k = 2391
1735619: zgemm: m = 51 n = 449 k = 24043 x 243
1747325: zgemm: m = 51 n = 449 k = 239 3 packing gntuju ( 243 x 243
最后两行表明,试图挽救错误的行可能会导致错误的数据,因为某些值可能会被截断或与其他数字连接
但是正则表达式应该足以识别有效行。所以我会这样做:
...
import re
...
...
pattern = r'\d+:\s\w+:\s+m\s+=\s+(\d+)\s+n\s+=\s+(\d+)\s+k\s+=\s+(\d+)\s*$'
rx = re.compile(pattern)
data = pd.DataFrame((m.groups() for line in ifile
for m in (rx.match(line),) if m),
columns=colnames).astype('int64')
...