如何从带有额外分隔符的 csv 在 python 中创建 pandas 数据框?

Posted

技术标签:

【中文标题】如何从带有额外分隔符的 csv 在 python 中创建 pandas 数据框?【英文标题】:How do I create a pandas dataframe in python from a csv with additional delimiters? 【发布时间】:2014-12-30 14:47:16 【问题描述】:

我有一个大的 csv(大约 400k 行),我希望将其转换为 python 中的数据框。原始文件有两列:一个文本列,后跟一个 int(或 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-X1 vs P-X-1),如何才能最好地完成?

【问题讨论】:

另外,我可能想简单地丢弃或跳过第二种格式的条目,其中包含额外的连字符,而不必解析它们。 我在不同的行中看到不同数量的连字符。结果不会是表格的。 DataFrame 每行中的列数必须相同。我误解了这个问题吗? P-X1 部分可以正确表示为 P-X1 或 P-X-1。后一种格式会更有用,但大部分数据都是前一种格式。同样,A01 更好地表示为 A-01,但大部分数据采用 A01 格式。因此,组件需要进行一些解析,以使所有数据正确地放入正确的存储桶中。 我想我知道了,你会查看我的答案吗? 【参考方案1】:

第一次尝试

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

【讨论】:

完美。使用containerFile = open('containers.csv','r') 创建一个文件对象,然后将其传递给df_from_file() 用于处理位于PATH 中的csv。谢谢你的回答!

以上是关于如何从带有额外分隔符的 csv 在 python 中创建 pandas 数据框?的主要内容,如果未能解决你的问题,请参考以下文章

python csv writer添加了额外的引号

闪亮:如何默认上传带有标题=T和分隔符=“,”的.csv?

如何从 Python 中的数据中删除多余的逗号

我们如何使用 python sdk 在 Apache Beam 中读取带有附件的 CSV 文件?

Python3避免在csv文件末尾引用和引用额外的行

如何使用 pandas.read_csv 在双引号之间读取带有千位分隔符的数字 [重复]