gpt4 book ai didi

python - 组合/平均多个数据文件

转载 作者:太空宇宙 更新时间:2023-11-03 11:30:42 25 4
gpt4 key购买 nike

我有一组数据文件(例如,“data####.dat”,其中 #### = 0001,...,9999),它们都具有相同 x 的通用数据结构- 第一列中的值,然后是具有不同 y 值的多个列。

data0001.dat:

#A < comment line with unique identifier 'A'
#B1 < this is a comment line that can/should be dropped
1 11 21
2 12 22
3 13 23

data0002.dat:

#A < comment line with unique identifier 'A'
#B2 < this is a comment line that can/should be dropped
1 13 23
2 12 22
3 11 21

它们基本上源 self 的程序使用不同种子的不同运行,我现在想将这些部分结果组合成一个公共(public)直方图,以便保留以“#A”开头的注释行(所有文件都相同)和其他评论行被删除。第一列保留,然后所有其他列应该对所有数据文件进行平均:

dataComb.dat:

#A < comment line with unique identifier 'A'
1 12 22
2 12 22
3 12 22

其中 12 = (11+13)/2 = (12+12)/2 = (13+11)/222 = (21+23)/2 = (22+22)/2 = (23+21)/2

我已经有一个 bash 脚本(可能是可怕的代码;但我不是很有经验......)通过运行 ./merge.sh data* > dataComb.dat 来完成这项工作命令行。它还检查所有数据文件是否具有相同的列数和第一列中的相同值。

merge.sh:

#!/bin/bash

if [ $# -lt 2 ]; then
echo "at least two files please"
exit 1;
fi

i=1
for file in "$@"; do
cols[$i]=$(awk '
BEGIN {cols=0}
$1 !~ /^#/ {
if (cols==0) {cols=NF}
else {
if (cols!=NF) {cols=-1}
}
}
END {print cols}
' ${file})
i=$((${i}+1))
done

ncol=${cols[1]}
for i in ${cols[@]}; do
if [ $i -ne $ncol ]; then
echo "mismatch in the number of columns"
exit 1
fi
done

echo "#combined $# files"
grep "^#A" $1

paste "$@" | awk "
\$1 !~ /^#/ && NF>0 {
flag=0
x=\$1
for (c=1; c<${ncol}; c++) { y[c]=0. }
i=1
while (i <= NF) {
if (\$i==x) {
for (c=1; c<${ncol}; c++) { y[c] += \$(i+c) }
i+= ${ncol}
} else { flag=1; i=NF+1; }
}
if (flag==0) {
printf(\"%e \", x)
for (c=1; c<${ncol}; c++) { printf(\"%e \", y[c]/$#) }
printf(\"\n\")
} else { printf(\"# x -coordinate mismatch\n\") }
}"

exit 0

我的问题是,对于大量数据文件,它会很快变慢,有时会抛出“打开的文件太多”错误。我看到简单地一次性粘贴所有数据文件(paste "$@")是这里的问题,但分批进行并以某种方式引入临时文件似乎也不是理想的解决方案。如果能在保留脚本调用方式的同时使它更具可扩展性,我将不胜感激,即所有数据文件作为命令行参数传递

我决定也将它发布到 python 部分,因为我经常被告知处理此类问题非常方便。然而,我几乎没有使用 python 的经验,但也许这是最终开始学习它的机会 ;)

最佳答案

下面附加的代码适用于 Python 3.3 并产生所需的输出,但有一些小警告:

  • 它从它处理的第一个文件中获取初始注释行,但不会费心检查之后的所有其他文件是否仍然匹配(即,如果您有多个以#A 开头的文件和一个以#A 开头的文件以 #C 开头,它不会拒绝 #C,即使它可能应该)。我主要想说明 merge 函数在 Python 中是如何工作的,并且认为添加这种类型的杂项有效性检查最好留作“家庭作业”问题。
  • 它也不会费心检查行数和列数是否匹配,如果不匹配可能会崩溃。将其视为另一个小作业问题。
  • 它将第一列右侧的所有列打印为浮点值,因为在某些情况下,它们可能就是这样。初始列被视为标签或行号,因此打印为整数值。

你可以像以前一样调用代码;例如,如果您将脚本文件命名为 merge.py,您可以执行 python merge.py data0001.dat data0002.dat,它会将合并的平均结果打印到标准输出,就像使用 bash 脚本一样。与早期的答案之一相比,该代码还具有更大的灵 active :它的编写方式原则上应该(我还没有实际测试以确保)能够合并具有任意数量列的文件,而不仅仅是恰好有三列的文件。另一个好处是:它不会在处理完文件后保持文件打开状态; with open(name, 'r') as infile: 行是一个 Python 习惯用法,即使 close() 从未被显式调用。

#!/usr/bin/env python

import argparse
import re

# Give help description
parser = argparse.ArgumentParser(description='Merge some data files')
# Add to help description
parser.add_argument('fname', metavar='f', nargs='+',
help='Names of files to be merged')
# Parse the input arguments!
args = parser.parse_args()
argdct = vars(args)

topcomment=None
output = {}
# Loop over file names
for name in argdct['fname']:
with open(name, "r") as infile:
# Loop over lines in each file
for line in infile:
line = str(line)
# Skip comment lines, except to take note of first one that
# matches "#A"
if re.search('^#', line):
if re.search('^#A', line) != None and topcomment==None:
topcomment = line
continue
items = line.split()
# If a line matching this one has been encountered in a previous
# file, add the column values
currkey = float(items[0])
if currkey in output.keys():
for ii in range(len(output[currkey])):
output[currkey][ii] += float(items[ii+1])
# Otherwise, add a new key to the output and create the columns
else:
output[currkey] = list(map(float, items[1:]))

# Print the comment line
print(topcomment, end='')
# Get total number of files for calculating average
nfile = len(argdct['fname'])
# Sort the output keys
skey = sorted(output.keys())
# Loop through sorted keys and print each averaged column to stdout
for key in skey:
outline = str(int(key))
for item in output[key]:
outline += ' ' + str(item/nfile)
outline += '\n'
print(outline, end='')

关于python - 组合/平均多个数据文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20818522/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com