将第一行中给出的 headers 的 ascii 文件读取到 pandas 数据帧中
reading an ascii file with headers given in the first rows into a pandas dataframe
我有一大组目录,其中有不同的列和每个列的不同 header 名称,其中每个 header 名称的描述在我的 ascii 开头作为注释给出连续的文件。将它们读入 pandas.DataFrame
的最佳方法是什么,同时它也可以设置列的名称,而无需从头开始定义它。以下是我的目录示例:
# 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
好的,假设您的所有 header 信息都以完全相同的方式编码,下面是我将如何做到这一点:
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个元素(索引=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
这是 Sextractor 格式的文件。 astropy.io.ascii
reader 本身就理解这种格式,因此阅读起来很容易:
>>> 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
...
请注意,使用 astropy ASCII reader 你会得到一个 table,它也保留了单位元数据。
如果您仍想将其转换为 pandas 数据框,使用 DataFrame(dat.as_array())
也很容易。 astropy 的 1.1 版(和当前的 master)将有方法 to_pandas
和 from_pandas
使这种转换更加稳健(参见 http://astropy.readthedocs.org/en/latest/table/pandas.html)。
我有一大组目录,其中有不同的列和每个列的不同 header 名称,其中每个 header 名称的描述在我的 ascii 开头作为注释给出连续的文件。将它们读入 pandas.DataFrame
的最佳方法是什么,同时它也可以设置列的名称,而无需从头开始定义它。以下是我的目录示例:
# 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
好的,假设您的所有 header 信息都以完全相同的方式编码,下面是我将如何做到这一点:
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个元素(索引=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
这是 Sextractor 格式的文件。 astropy.io.ascii
reader 本身就理解这种格式,因此阅读起来很容易:
>>> 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
...
请注意,使用 astropy ASCII reader 你会得到一个 table,它也保留了单位元数据。
如果您仍想将其转换为 pandas 数据框,使用 DataFrame(dat.as_array())
也很容易。 astropy 的 1.1 版(和当前的 master)将有方法 to_pandas
和 from_pandas
使这种转换更加稳健(参见 http://astropy.readthedocs.org/en/latest/table/pandas.html)。