2013-10-22 48 views
3

我的教授使用IDL并向我发送了一个ASCII数据文件,我需要这些文件最终能够读取和操作。添加名称并将数据类型分配给ASCII数据

他用下面的命令来读取数据:

readcol, 'sn-full.txt', format='A,X,X,X,X,X,F,A,F,A,X,X,X,X,X,X,X,X,X,A,X,X,X,X,A,X,X,X,X,F,X,I,X,F,F,X,X,F,X,F,F,F,F,F,F', $ 
sn, off1, dir1, off2, dir2, type, gal, dist, htype, d1, d2, pa, ai, b, berr, b0, k, kerr 

这里的前两行是什么样的图片:http://i.imgur.com/hT7YIE3.png

因为我不会成为一名天文学家,我我正在使用Python,但由于我是新手,我很难读取数据。我知道他的代码将数据类型A(字符串数据)分配给第一列,使用X跳过第二列六,然后将数据类型F(浮点)分配给第七列,等等。然后sn被分配到第一列不跳过,等等。

我一直在试图通过使用numpy.loadtxt("sn-full.txt")ascii.read("sn-full.txt")复制此,但我不知道如何输入dtype参数。我知道我可以将所有内容分配给某种数据类型,但是如何将数据类型分配给各个列?

+0

欢迎来到stackoverflow! –

+0

尝试[genfromtxt](http://docs.scipy.org/doc/numpy/reference/generated/numpy.genfromtxt.html#numpy.genfromtxt)也可以在[导入数据]的基础知识中找到好的部分(http:// docs .scipy.org/DOC/numpy的/用户/ basics.io.genfromtxt.html)。如果列是字符串,那么您将不得不以字节为单位给出确切的大小。一个简单的方法来分配'dtypes'作为元组,EG:'dtype = [('str1',str,8),('var1',float),('var2',int)]''。特别参见[数据类型]部分(http://docs.scipy.org/doc/numpy/user/basics.io.genfromtxt.html#choosing-the-data-type)。 –

+0

即使你要成为一名天文学家,你应该使用Python(或者也许是朱莉娅,甚至是Ruby),而不是将自己限制为一种专有语言:) – Iguananaut

回答

4

使用astropy.io.ascii你应该能够相对容易地阅读您的文件:

from astropy.io import ascii 
# Give names for ALL of the columns, as there is no easy way to skip columns 
# for a table with no column header. 
colnames = ('sn', 'gal_name1', 'gal_name2', 'year', 'month', 'day', ...) 
table = ascii.read('sn_full.txt', Reader=ascii.NoHeader, names=colnames) 

这给你所有的数据列的表。事实上,你有一些你不需要的列是不是一个问题,除非表是超长行。对于您显示的表格,您不需要明确指定dtypes,因为io.ascii.read会正确地指出它们。

这里的一个小问题是,你所展示的表格实际上是一个固定宽度的表格,这意味着所有的列都垂直排列。请注意,第一行以1998S NGC 3877开头。只要每一行都有相同的模式,并且有三个以空格分隔的列表示超新星名称和银河系名称为两个单词,那么你很好。但是如果任何星系名称都是单个单词,那么解析将失败。我怀疑,如果IDL readcol正在工作,那么相应的io.ascii版本应该开箱即用。如果不是,那么io.ascii有一种读取固定宽度表格的方式,您可以明确地提供列名称和位置。

[编辑] 看起来像这种情况下,需要一个固定宽度的阅读器来通知解析器如何拆分列而不是仅使用空格作为分隔符。所以基本上你需要在一个表文件,其中第一个给出了列名的顶部添加两行,第二个指示每一列的跨度破折号:

a  b   c   
---- ------------ ------ 
1.2 hello there 2 
2.4 worlds   3 

它也可以在astropy.io.ascii到如果您没有修改输入数据文件的选项,只需通过代码指定每列的开始和停止位置,例如:

>>> ascii.read(table, Reader=ascii.FixedWidthNoHeader, 
       names=('Name', 'Phone', 'TCP'), 
       col_starts=(0, 9, 18), 
       col_ends=(5, 17, 28), 
      ) 
+0

谢谢你的回应。我相信这应该起作用。但我遇到了一个问题。在一些行中,最后一列的条目是两个词,它们导致InconsistentTableError:头列(47)的数量与数据行26处的数据列(48)不一致。如果我添加另一个头列,则得到相同的错误但这次在第0行。任何建议来解决这个问题? – user2909019

+1

所以你可能需要为你的文件添加一个头文件并使用'FixedWidthTwoLine'阅读器。如果您遵循[第一个示例](http://astropy.readthedocs.org/en/v0.2.4/io/ascii/fixed_width_gallery.html#fixedwidthtwoline),应该比较清楚该怎么做。 –

+0

最后一个问题。我终于可以读取这些数据,但我想知道是否有更简单的方法来操作数据。例如,假设我想为三个不同的超新星添加“off1”的值。现在我只是使用'SNdata ['off1'] [0] + SNdata ['off1'] [1] + SNdata ['off1'] [2]'。有没有更简单的方法来做到这一点? – user2909019

2

http://casa.colorado.edu/~ginsbura/pyreadcol.htm看起来像它做你想做的。它模拟IDL的readcol函数。

另一种可能性是https://pypi.python.org/pypi/fortranformat。看起来它可能更有能力,你看的数据是固定格式的,格式说明符(X,A等)是Fortran格式说明符。

+0

readcol(http://code.google.com/p/) agpy/source/browse/trunk/agpy/readcol.py)是一个很好的解决方案,我仍然使用它(我写它),但是'np.loadtxt'现在几乎可以完成所有相同的功能。 – keflavich

0

我会使用Pandas为特定的目的。做到这一点最简单的方法是,假设你的列单制表符分隔:

import pandas as pd 
import scipy as sp # Provides all functionality from numpy, too 
mydata = pd.read_table(
      'filename.dat', sep='\t', header=None, 
      names=['sn', 'gal_name1', 'gal_name2', 'year', 'month',...], 
      dtype={'sn':sp.float64, 'gal_name1':object, 'year':sp.int64, ...},) 

(字符串这里落入一般“对象”数据类型)。

每列现在都有一个名称,可以作为mydata['colname']进行访问,然后可以像常规numpy 1D数组一样切片,例如, mydata['colname'][20:50]等等,等等

熊猫有内置的绘图调用matplotlib,所以你可以通过mydata['column'].plot()迅速获得数值类型列的概述,或两个不同的列对彼此mydata.plot('col1', 'col2')。所有正常的绘图关键字都可以通过。

如果您想在正常的matplotlib例程中绘制数据,您可以将列传递给matplotlib,在那里它们将被视为普通的Numpy向量。 每列可以作为mydata['colname'].values作为一个普通的Numpy向量来访问。

编辑

如果您的数据不是均匀分开,numpy的的genfromtxt()功能更好。然后你可以将它转换成Pandas DataFrame

mydf = pd.DataFrame(myarray, columns=['col1', 'col2', ...], 
        dtype={'col1':sp.float64, 'col2':object, ...})