Python:读取可变数量的数字列

时间:2017-04-05 11:56:25

标签: python arrays multiple-columns

默认情况下,我的python脚本将从stdin获取数据并写入stdout。但是,如果我指定某些命令行选项,那么我可以从文件读取或写入文件。

该脚本只会读取两列数字,这些数字由制表符和/或空格分隔。我需要它,它将读取2个或更多列的数字(我有其他脚本,我将其中一个的输出传输到另一个的输入)。

这就是我所拥有的:

def main(argv):
  fin=sys.stdin
  fout=sys.stdout
  w=3
  plot=False
  graph=False
  ifile="stdin"
  ofile="stdout"
  filt="Median"
  ydata=False
  try:
      opts, args=getopt.getopt(argv,"hi:o:w:ps:qf:y",["ifile=","ofile="])
  except getopt.GetoptError:
    print sys.argv[0] + ' [-i <inputfile>] [-o <outputfile>] [-w <int>] [-p] [-s <imagefile>] [-q] [-f <int>] [-y]'
    sys,exit(1)
  for opt, arg in opts:
    if opt=='-h':
      print sys.argv[0] + ' [-i <inputfile>] [-o <outputfile>] [-w <int>] [-p] [-s <imagefile>] [-q] [-f <int>] [-y]n'
      print '   -w  filter window size (default=3)'
      print '   -p  display plot'
      print '   -s  save plot as imagefile (eps, jpeg, jpg, pdf, pgf, png, ps, raw, rgba, svg, svgz, tif, tiff)'
      print '   -i  if no inputfile is specified, read from STDIN'
      print '   -o  if no outputfile is specified, print to STDOUT'
      print '   -f  integer: 1=median (default), 2=moving average, 3=Wiener'
      print '   -q  quiet; suppress output'
      print '   -y  include y-data in output'
      sys.exit()
    elif opt in ("-i", "--ifile"):
      ifile=arg
    elif opt in ("-o", "--ofile"):
      ofile=arg
    elif opt in ("-q"):
      ofile="/dev/null"
    elif opt in ("-w"):
      w=int(arg)
    elif opt in ("-p"):
      plot=True
    elif opt in ("-f"):
      if int(arg)==2:
        filt="Moving Average"
      elif int(arg)==1:
        filt="Median"
      elif int(arg)==3:
        filt="Wiener"
    elif opt in ("-s"):
      graph=True
      imagefile=arg
    elif opt in ("-y"):
      ydata=True

  fin=open(ifile,'r')
  lines=fin.readlines()
  fin.close()

# Initialize two lists
  xl = []
  y1l = []

  for line in lines:
      p = line.split()
      xl.append(float(p[0]))
      y1l.append(float(p[1]))

# Convert the lists to arrays
  x = np.array(xl)
  y1 = np.array(y1l)

  if filt=="Median":
    yf=median(y1,width=w)
  elif filt=="Moving Average":
    yf=movingaverage(y1,w)
  elif filt=="Wiener":
    yf=wiener(y1,mysize=w)

  fout=open(ofile,'w')
  if ydata:
    outdata=np.array([x,y1,yf])
    fmt=['%4.1f','%13.5e','%13.5e']
  else:
    outdata=np.array([x,yf])
    fmt=['%4.1f','%13.5e']
  outdata=outdata.T
  np.savetxt(fout, outdata, fmt)
  fout.close()

第一列将存储在名为xl的列表中,然后转换为名为x的数组。

第二列将存储在名为y1l的列表中,然后转换为名为y1的数组。

第三列(如果有的话)将存储在名为y2l的列表中,然后转换为名为y2的数组。

等等。

列数应存储在变量中。

或者,或许,将所有输入数据存储到多维列表然后再存储数组可能会更好?我实际上甚至不需要这些清单;它们仅用于中间步骤以将数据导入数组。如果可以跳过将数据存储在列表中,并直接存储到数组中,那就更好了。

2 个答案:

答案 0 :(得分:0)

考虑使用numpy.loadtxt直接加载所有列的文本文件,避免使用嵌套列表的for循环。然后,如果需要,使用numpy.apply_along_axis跨列运行函数。

mat = np.loadtxt(ifile, delimiter="\t")

if filt=="Median":
    output_mat = np.apply_along_axis(median, 0, w)

elif filt=="Moving Average":
    output_mat = np.apply_along_axis(movingaverage, 0, w)

elif filt=="Wiener":
    output_mat = np.apply_along_axis(weiner, 0, w)

np.savetxt(ofile, output_mat, delimiter='\t')

答案 1 :(得分:0)

这是我提出的有效方法。

#!/usr/bin/python

import numpy as np
import sys
import os
import matplotlib.pyplot as plt
import math

# set the default input to STDIN
infile=sys.stdin

# load the data from input
data=np.loadtxt(infile)
rows=len(data)
cols=len(data[0])

# find the minimum and maximum x-values
xmin=min(data[:,0])
xmax=max(data[:,0])

# create the plot
fig=plt.figure()
fig.set_size_inches(16,9)
fig.set_dpi(120)
plt.plot(data[:,0],data[:,1:])
plt.ylim(ymin=1e-6)
plt.xlim(xmin,xmax)
plt.grid(which='major',linestyle='-',linewidth='0.3')
plt.xlabel('energy (eV/u)')
plt.ylabel(r'cross section (10$^{-16}$ cm$^{2}$)')
plt.xscale('log',basex=10)
plt.yscale('log',basey=10)
plt.show()