pd.read_csv 如果逗号在括号内,则忽略它

Posted

技术标签:

【中文标题】pd.read_csv 如果逗号在括号内,则忽略它【英文标题】:pd.read_csv ignore comma if it is inside parenthesis 【发布时间】:2021-12-01 02:16:57 【问题描述】:

我有一个非常简单的文件:

[Name]
Streamline 1


[Data]
X [ m ], Y [ m ], Z [ m ], Velocity [ m s^-1 ]
2.66747564e-01, 0.00000000e+00, 2.03140453e-01, (0.00000000e+00, 8.17744827e+00, 0.00000000e+00)
2.66958952e-01, 0.00000000e+00, 2.07407191e-01, (0.00000000e+00, 6.77392197e+00, 0.00000000e+00)
2.63460875e-01, 0.00000000e+00, 2.06593186e-01, (0.00000000e+00, 7.04168701e+00, 0.00000000e+00)
2.65424699e-01, 0.00000000e+00, 2.00831652e-01, (0.00000000e+00, 8.93691921e+00, 0.00000000e+00)
2.70607203e-01, 0.00000000e+00, 2.02286631e-01, (0.00000000e+00, 8.45830917e+00, 0.00000000e+00)
2.68299729e-01, 0.00000000e+00, 1.97365344e-01, (0.00000000e+00, 1.00771456e+01, 0.00000000e+00)
...

我需要将速度作为矢量加载到一行中。

我的基本代码:

df = pd.read_csv("C:/Users/Marek/Downloads/0deg-5ms.csv", skiprows=5)

但是这种尝试导致第一个 2 列成为索引,其余的分为 4 列。 index_col=False 可以解决索引的问题,但是会导致索引超出范围。我需要一个分隔符,隐含地告诉熊猫忽略括号中的任何内容。我认为python ignore the separator withing brackets while reading a csv file 可能有用,但是是的,我到处都有空间。我找到了一些使用扩展函数加载文件并按行处理的解决方案,例如CSV file containing column with occasional comma in parentheses crashes pandas.read_csv和Load CSV with data surrounded by parentheses into a pandas dataframe。然而,我相信这是一个非常简单的场景,因为所有行都是相似的,并且可以通过添加delimiter='some_regex' 来解决。但是,我无法弄清楚这个正则表达式的外观。它应该寻找分隔符,,而不是(.*,.*)

我尝试过以下操作,但这会导致单列:

df = pd.read_csv("C:/Users/Marek/Downloads/0deg-5ms.csv", skiprows=5,  delimiter=',^(\(.*,.*\))')

编辑:得到这样的东西 - ,|(?:(\(.*,.*\))),但这会在每个逗号后添加一个空列。

【问题讨论】:

考虑使用read_fwf 而不是read_csv 【参考方案1】:

您可以手动解析文件:

data = []
with open('data.csv') as fp:
    [next(fp) for i in range(5)]  # skiprows=5
    headers = [c.strip() for c in next(fp).split(',')]
    for line in fp:
        data.append([i.strip() for i in re.split(r',(?![^\(]*[\)])', line)])

df = pd.DataFrame(data, columns=headers).apply(pd.eval)

输出:

>>> df
    X [ m ]  Y [ m ]   Z [ m ]     Velocity [ m s^-1 ]
0  0.266748      0.0  0.203140  [0.0, 8.17744827, 0.0]
1  0.266959      0.0  0.207407  [0.0, 6.77392197, 0.0]
2  0.263461      0.0  0.206593  [0.0, 7.04168701, 0.0]
3  0.265425      0.0  0.200832  [0.0, 8.93691921, 0.0]
4  0.270607      0.0  0.202287  [0.0, 8.45830917, 0.0]
5  0.268300      0.0  0.197365  [0.0, 10.0771456, 0.0]

>>> df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 6 entries, 0 to 5
Data columns (total 4 columns):
 #   Column               Non-Null Count  Dtype  
---  ------               --------------  -----  
 0   X [ m ]              6 non-null      float64
 1   Y [ m ]              6 non-null      float64
 2   Z [ m ]              6 non-null      float64
 3   Velocity [ m s^-1 ]  6 non-null      object 
dtypes: float64(3), object(1)
memory usage: 320.0+ bytes

>>> type(df.iloc[0, 3])  # [0.0, 8.17744827, 0.0]
list

>>> type(df.iloc[0, 3][1])  # 8.17744827
float

【讨论】:

谢谢你的回答,好像是正确的。但是,我一直在寻找一种单线,除了 read_csv 之外不使用任何东西,并同时设法解决它:) 我正在使用相同的正则表达式... 啊,我什至没有注意到它是一样的,你是对的。赞成您的答案,因为它很好且正确,只是在寻找极简主义的解决方案。【参考方案2】:

经过多次尝试,我找到了如何在此基础上创建一个非常简单的单线的答案。如果有人有兴趣,这里是:

df = pd.read_csv("C:/Users/Marek/Downloads/0deg-5ms.csv", skiprows=5,  delimiter=',(?![^\(]*[\)])', engine="python")

分隔符检查括号外所有内容中的逗号。简单就像一个魅力:)

【讨论】:

以上是关于pd.read_csv 如果逗号在括号内,则忽略它的主要内容,如果未能解决你的问题,请参考以下文章

pandas read_csv,最后一列包含逗号

在逗号上拆分字符串但忽略双引号内的逗号?

用逗号分割字符串,但忽略括号或引号中的逗号

分割逗号时,如何忽略括号中的逗号?

如何在忽略引号内的任何逗号的情况下用逗号分隔? [复制]

Java正则表达式用逗号分割字符串,但忽略引号和括号[重复]