2015-07-13 25 views
2

我有一个巨大的一组目录有不同的列和每个列不同的标题名称,每个标题名称的描述作为注释给出我的ascii文件连续开始。将它们读入pandas.DataFrame的最佳方法是什么,同时它可以设置列的名称,而无需从头开始定义它。以下是我的目录的例子:阅读一个ascii文件,头部给出的标题为一个熊猫数据框

# 1 MAG_AUTO   Kron-like elliptical aperture magnitude   [mag] 
# 2 rh     half light radius (analyse)      [pixel] 
# 3 MU_MAX    Peak surface brightness above background  [mag * arcsec**(-2)] 
# 4 FWHM_IMAGE   FWHM assuming a gaussian core     [pixel] 
# 5 CLASS_STAR   S/G classifier output       
18.7462 4.81509 20.1348 6.67273 0.0286538 
18.2440 7.17988 20.6454 21.6235 0.0286293 
18.3102 3.11273 19.0960 8.26081 0.0430532 
21.1751 2.92533 21.9931 5.52080 0.0290418 
19.3998 1.86182 19.3166 3.42346 0.986598 
20.0801 3.52828 21.3484 6.76799 0.0303842 
21.9427 2.08458 22.0577 5.59344 0.981466 
20.7726 1.86017 20.8130 3.69570 0.996121 
23.0836 2.23427 23.3689 4.49985 0.706207 
23.2443 1.62021 23.1089 3.54191 0.973419 
20.6343 3.99555 21.9426 6.94700 0.0286164 
23.4012 2.00408 23.3412 4.35926 0.946349 
23.8427 1.54819 23.8241 3.83407 0.897079 
20.3344 2.69910 20.9401 4.38988 0.0355277 
21.7506 2.43451 22.2115 4.62045 0.0786921 
+0

我们可以在这个问题上得到更多的限制吗? (例如,我们应该预计什么是最大列数?) –

+0

@PaulH从23000行的顺序! – Dalek

+0

你有23,000列的文件? –

回答

2

好吧,假设你所有的头信息中完全相同的方式编码的,这里是我会怎么做:

import re 

import pandas 

COMMENT_CHAR = '#' 
columns = [] 
with open('test.dat', 'r') as td: 
    for line in td: 

     # find the commented lines 
     if line[0] == COMMENT_CHAR: 
      info = re.split(' +', line) 
      columns.append(info[2]) 

     # when we seethe first line that doesn't start with 
     # COMMENT_CHAR, we pass the remaining lines of the 
     # file to pandas.read_table and break our loop 
     else: 
      _dfs = [ 
       pandas.DataFrame([line.split(' ')], columns=columns, dtype=float), 
       pandas.read_table(td, sep='\s', header=None, names=columns) 
      ] 
      df = pandas.concat(_dfs, ignore_index=True) 

要打破初始解析位,re.split(' +', line)变成这样:成

# 1 MAG_AUTO Kron-like elliptical aperture magnitude [mag]

['#', '1', 'MAG_AUTO', 'Kron-like', 'elliptical', 'aperture', 'magnitude', '[mag]']

所以我们把列名作为3元素(index = 2)。

这一切都产生了数据帧,看起来像这样:

print(df.head()) 
    MAG_AUTO  rh MU_MAX FWHM_IMAGE CLASS_STAR 
0 18.7462 4.81509 20.1348  6.67273 0.0286538 
1 18.2440 7.17988 20.6454 21.62350 0.028629 
2 18.3102 3.11273 19.0960  8.26081 0.043053 
3 21.1751 2.92533 21.9931  5.52080 0.029042 
4 19.3998 1.86182 19.3166  3.42346 0.986598 

而且df.info()给我们:

<class 'pandas.core.frame.DataFrame'> 
Int64Index: 15 entries, 0 to 14 
Data columns (total 5 columns): 
MAG_AUTO  15 non-null float64 
rh   15 non-null float64 
MU_MAX  15 non-null float64 
FWHM_IMAGE 15 non-null float64 
CLASS_STAR 15 non-null float64 
dtypes: float64(5) 
memory usage: 720.0 bytes 
+1

您正在跳过第一行数据。当你找到一行不以'#'开始的行时,你必须在数据中包含该行。 –

+0

啊,很好,@WarrenWeckesser。我的第一个想法是打破循环,用'skiprows'参数将整个文件送回'read_table'。思考? –

+0

@PaulH答案还存在问题。对于最后一列中的第一行数据,我有:'df ['CLASS_STAR'] [0] '0.0286538 \ n'' – Dalek

9

这是Sextractor格式的文件。该astropy.io.asciireader本身理解这种格式,所以这是一个管理单元,以阅读:

>>> from astropy.io import ascii 
>>> dat = ascii.read('table.dat') 
>>> dat 
<Table masked=False length=3> 
MAG_AUTO rh  MU_MAX FWHM_IMAGE CLASS_STAR 
    mag   mag/arcsec2 pix    
float64 float64 float64  float64 float64 
-------- ------- ------------- ---------- ---------- 
18.7462 4.81509  20.1348 6.67273 0.0286538 
    18.244 7.17988  20.6454 21.6235 0.0286293 
18.3102 3.11273  19.096 8.26081 0.0430532 
... 

注意,当使用ASCII astropy读者你得到一个表,也保留了单元的元数据。

如果您仍想将其转换为容易的的熊猫数据框。 astropy版本1.1(和当前主版本)的方法有to_pandasfrom_pandas,这使得此转换更健壮(请参阅http://astropy.readthedocs.org/en/latest/table/pandas.html)。

+1

我不是天文学家,但是天文学似乎是一个很好的资源。 –

相关问题