首页 > 解决方案 > 创建 Pandas 数据框时如何忽略括号内的分隔符?

问题描述

我正在使用在带有参数信息的实际数据之前有注释的数据文件。最后一条评论总是包含列标题,但评论的数量是可变的。

一些示例数据文件:

# Model type:               AE9
# Particle species:         e-
# Flux type:                1PtDiff
# Flux direction:           Omnidirectional
# Energy levels (MeV):      0.04 0.07 0.1 0.25 0.5 0.75 1 1.5
#
# Accumulation mode:        Interval, length = 86400 seconds (1 days)   
#
# Time format:              Year, day_of_year, GMT_seconds_of_day
# Coordinate system:        GDZ (WGS84 Geodetic) in km
# Data Delimiter:           comma
#
# datetime(year,ddd,gmtsec),alt(km),lat(deg),lon(deg),fluence
2015,1,43200.00,0.00000,0.000000,0.000000,2.73859496e+012

其他:

# Model type:               AP9
# Particle species:         H+
# Flux type:                1PtDiff
# Flux direction:           Omnidirectional
# Energy levels (MeV):       0.1 0.2 0.4 0.6
#
# Time format:              Year, Month, Day, Hour, Minute, Seconds
# Coordinate system:        GDZ (WGS84 Geodetic) in km
# Data Delimiter:           comma
#
# datetime(year,mon,day,hr,min,sec),alt(km),lat(deg),lon(deg),flux
2015,1,1,0,0,0.01,1464.49524,0.000000,259.862461,1.77883217e+004

只有一列对应日期时间信息的示例:

# Model type:               AP9
# Particle species:         H+
# Flux type:                1PtDiff
# Flux direction:           Omnidirectional
# Energy levels (MeV):       0.1 0.2 0.4 0.6
#
# Time format:              Modified Julian Date
# Coordinate system:        GDZ (WGS84 Geodetic) in km
# Data Delimiter:           comma
#
# datetime(mjd),alt(km),lat(deg),lon(deg),flux
57023.00000000,1464.49524,0.000000,259.862461,1.77883219e+004

当我创建这样的数据框时:

data_frame = pd.read_csv(
                 file_name,
                 skiprows    = params_dict['Header Line'],
                 sep         = ',',
                 escapechar  = '#',
                 memory_map  = True,
                 index_col   = 0
)

仅当日期时间括号内没有逗号(分隔符)时,它才会根据需要返回数据帧,例如此标题行:

# datetime(mjd),alt(km),lat(deg),lon(deg),flux

在数据框中,不带逗号的日期时间的输出如下所示:

                               alt(km)   lat(deg)    lon(deg)          flux
datetime(mjd)
57023.000000                1464.49524   0.000000  259.862461  17788.321900

它与诸如此类的事情变得混乱# datetime(year,ddd,gmtsec)

                ddd  gmtsec)   alt(km)  lat(deg)  lon(deg)       fluence  
 datetime(year
 2015              1  43200.0      0.0       0.0       0.0  1.937139e+09

显然,由于分隔符,它将日期时间的每个部分作为另一个列名读取。

最长的日期时间类型有六列部分,如下所示:

# datetime(year,mon,day,hr,min,sec)

期望的输出:

                            alt(km)  lat(deg)  lon(deg)       fluence  
 datetime(year,ddd,gmtsec) 
 2015,1,43200.0                 0.0       0.0       0.0  1.937139e+09

如何在调用时忽略列标题行中括号内的分隔符pd.read_csv()?我无法更改数据文件本身。我的目标是解析列名,以便将datetime(year,ddd,gmtsec)ordatetime(year,mon,day,hr,min,sec)读取为单个列标题。我总是想让我的日期时间列成为我的数据框的索引。

我的猜测是可以在正则表达式中找到答案,但我不知道如何实现它。先感谢您。

标签: pythonpython-3.xpandasdataframe

解决方案


我已经有一个从文件中获取所有参数的函数,所以我添加了一个正则表达式来查找标题行中的第一对括号。我计算了这些括号内有多少个逗号,以确定文件有多少个日期时间列。然后,我在列表推导中使用该计数来创建一个序数索引列表以供data_frame.columns()稍后传递。我将数据框的索引设置为创建 MultiIndex 的所有日期时间列。

输入:

import re

import pandas as pd

def get_params():
    params_dict = {}

    with open('data.csv') as current_file:
        for i, line in enumerate(current_file):
            if ':' in line:
                dict_key   = line.split(':')[0].strip(' #')
                dict_value = line.split(':')[1].strip()

                params_dict[dict_key] = dict_value

            if 'datetime' in line:
                # Return contents of datetime parentheses as string
                datetime_cols = re.findall(r'\(((?:\w+\,*)+)\)', line)[0]
                dt_cols_count = datetime_cols.count(',')

                # Create list of ordinal indices to set datetime columns in dataframe
                ind_list = [i for i in range(0, dt_cols_count + 1)]
                params_dict['Index List'] = ind_list

                # Grab header line location to determine number of rows to skip in creating dataframe                
                params_dict['Header Line'] = i

                return params_dict

params_dict = get_params()

data_frame = pd.read_csv(
                 'data.csv',
                 skiprows    = params_dict['Header Line'],
                 sep         = ',',
                 escapechar  = '#',
                 memory_map  = True,
)

data_frame.set_index(list(data_frame.columns[params_dict['Index List']]), inplace = True)

print(data_frame)

输出:

                                       alt(km)   lat(deg)    lon(deg)          flux
datetime(year  mon  day  hr min sec)
2015           1   1   0  0   0.01  1464.49524   0.000000  259.862461  17788.321700

这适用于我使用的所有日期时间格式,但我确信它远非最佳解决方案。


推荐阅读