我有这样的矩阵(其余的第一列名称是值,分隔符i标签):
name1 A1 B1 C1 D1
name2 A2 B2 C2 D2
矩阵可能很大(平均约有数百行和列)。大小相同。我可以期待零值。
我需要这样的输出:
name1 A1 B1 C1 D1 A1/B1 A1/C1 A1/D1
name2 A2 B2 C2 D2 A2/B2 A2/C2 A2/D2
此组合保存到新文件。然后进行另一组合:
name1 A1 B1 C1 D1 B1/A1 B1/C1 B1/D1
name2 A2 B2 C2 D2 B2/A2 B2/C2 B2/D2
,依此类推=>将矩阵中的每一列与其余列分开,并保存为TSV到新文件中。并四舍五入到小数点后三位。
我可以使用脚本手动完成此操作
awk '{OFS="\t"}{$6=$2/($3+0.001); $7=$2/($4+0.001); $8=$2/($5+0.001)}1' input_file.tsv
为什么我加0.001的原因是不可能除以零。我可以使用wile循环创建shell脚本,但是需要很长时间。
对于此过程的任何自动化,我将感到非常高兴。
答案 0 :(得分:5)
能否请您尝试以下。同样通过查看您的尝试,我假设您的Input_file由空格而不是逗号分隔,如果除空格之外还有其他分隔符,则在以下代码中也添加BEGIN{FS=","}
(以逗号为例)。感谢@accdias添加了逻辑来也删除了控制M个字符
awk '
{
gsub(/\r/,"")
}
{
nf=NF
close(out_file)
for(k=2;k<=nf;k++){
out_file=""
for(i=2;i<=nf;i++){
if($i!=0){
$(NF+1)=sprintf("%.03f",$k/$i)
}
else{
$(NF+1)=sprintf("%s","NaN")
}
}
out_file=k"field_out_file"
print >> (out_file)
NF=nf
}
}' Input_file
代码处理的是什么:
2field_out_file
,这意味着第二个字段将被整个Input_file /中的所有元素分隔。close
函数可避免出现诸如too many files opened
之类的错误。0
的值,并在输出中输出NaN
。答案 1 :(得分:1)
由于您用python-3.x
标记了问题,因此以下是一个脚本,可以实现您想要的功能(由于f-strings
,它需要Python 3.6 +):
from pathlib import Path
import csv
source = Path('input.tsv')
with source.open() as src:
csvreader = csv.reader(src, dialect='excel-tab')
# get number of columns and rewind
cols = len(next(csvreader)[1:])
src.seek(0)
csvwriters = []
# create a csv.writer for each column
for i in range(cols):
# output_col_01.tsv, output_col_02.tsv ...
csvwriters.append(
csv.writer(
Path(f'output_col_{i + 1:02d}.tsv').open('w'),
dialect='excel-tab'
)
)
nan = float('nan')
for name, *cols in csvreader:
for i, a in enumerate(cols):
row = [name]
for j, b in enumerate(cols):
# skip the quotient of a col by itself
if i != j:
a = float(a)
b = float(b)
# nan if division by zero
row.append(round(a / b, 4) if b else nan)
csvwriters[i].writerow(row)
我没有为除数为0.001
的操作添加0
,而是选择返回float('nan')
。
它不会将列本身分开,而是将商四舍五入到小数点后四位。
最后,如果您使用的Python版本早于3.6(由于pathlib.Path()
,您仍需要Python版本3.4+),然后替换以下行:
Path(f'output_col_{i + 1:02d}.tsv').open('w'),
具有:
Path('output_col_%02d.tsv' % (i + 1)).open('w'),
这是必须的,因为f-strings
是在Python 3.6中引入的。