如何从带有额外分隔符的CSV创建pandas DataFrame?

3 投票
1 回答
772 浏览
提问于 2025-05-01 09:48

我有一个很大的csv文件,大约有40万行,我想把它转成Python中的数据框(dataframe)。这个文件原本有两列:一列是文本,另一列是整数(或者是空值NAN)。

举个例子:

...
P-X1-6030-07-A01    368963
P-X1-6030-08-A01    368964
P-X1-6030-09-A01    368965
P-A-1-1011-14-G-01  368967
P-A-1-1014-01-G-05  368968
P-A-1-1017-02-D-01  368969
...

我还想把文本列拆分成多个列,按照示例文本最后三行的格式来拆分(比如P A 1 1017 02 D 01 368969)。

需要注意的是,文本字段的格式可能会有所不同(比如P-X1P-X-1),那么我该怎么做才能最好地实现这个目标呢?

暂无标签

1 个回答

4

第一次尝试

read_csv的说明书上说它可以用正则表达式,但这似乎不太对。经过查看源代码后发现,它其实只是接受一系列字符,这些字符可以用来组成一个字符集,后面跟着一个+,所以下面给sep的参数会用来创建一个像这样的正则表达式:

`[- ]+`. 

导入必要的库以便重现:

import pandas as pd
import StringIO

你可以使用一组字符作为分隔符,不过用pd.read_csv来解析不匹配的行是行不通的,但如果你想单独解析它们:

pd.read_csv(StringIO.StringIO('''P-X1-6030-07-A01    368963
P-X1-6030-08-A01    368964
P-X1-6030-09-A01    368965'''), sep=r'- ') # sep arg becomes regex, i.e. `[- ]+`

还有

pd.read_csv(StringIO.StringIO('''P-A-1-1011-14-G-01  368967
P-A-1-1014-01-G-05  368968
P-A-1-1017-02-D-01  368969'''), sep=r'- ')

但是read_csv显然不能使用真正的正则表达式作为分隔符。


最终解决方案

这意味着我们需要一个自定义的解决方案:

import re
import StringIO
import pandas as pd

txt = '''P-X1-6030-07-A01    368963
P-X1-6030-08-A01    368964
P-X1-6030-09-A01    368965
P-A-1-1011-14-G-01  368967
P-A-1-1014-01-G-05  368968
P-A-1-1017-02-D-01  368969'''

fileobj = StringIO.StringIO(txt)

def df_from_file(fileobj):
    '''
    takes a file object, returns DataFrame with columns grouped by 
    contiguous runs of either letters or numbers (but not both together)
    '''
    # unfortunately, we must materialize the data before putting it in the DataFrame
    gen_records = [re.findall(r'(\d+|[A-Z]+)', line) for line in fileobj]
    return pd.DataFrame.from_records(gen_records)

df = df_from_file(fileobj)

现在df返回:

   0  1  2     3   4  5   6       7
0  P  X  1  6030  07  A  01  368963
1  P  X  1  6030  08  A  01  368964
2  P  X  1  6030  09  A  01  368965
3  P  A  1  1011  14  G  01  368967
4  P  A  1  1014  01  G  05  368968
5  P  A  1  1017  02  D  01  368969

撰写回答