Python 使用pd.read_CSV(不规则分隔符,自定义NA)读取borked CSV文件
我正在读取CSV数据以用作熊猫数据帧,但CSV似乎没有遵循任何合理的约定(除了使用Python 使用pd.read_CSV(不规则分隔符,自定义NA)读取borked CSV文件,python,pandas,csv,unicode,separator,Python,Pandas,Csv,Unicode,Separator,我正在读取CSV数据以用作熊猫数据帧,但CSV似乎没有遵循任何合理的约定(除了使用;作为分隔符外,每个人都应该……)。看起来,唯一的目标是让它们在文本编辑器中打开时看起来好看 以下是一些示例(设置为变量,以便读者可以使用这些示例): 好的,十进制逗号(easy)、分号分隔符(easy)、dayfirst(easy)和一组元数据(skiprows,也很容易) print(ts生成一个漂亮的数据帧 val date 1939-10-01 1.1 1939-12-01
;
作为分隔符外,每个人都应该……)。看起来,唯一的目标是让它们在文本编辑器中打开时看起来好看
以下是一些示例(设置为变量,以便读者可以使用这些示例):
好的,十进制逗号(easy)、分号分隔符(easy)、dayfirst(easy)和一组元数据(skiprows,也很容易)
print(ts
生成一个漂亮的数据帧
val
date
1939-10-01 1.1
1939-12-01 1.0
1940-01-01 10.0
而ts.index
是一个很好的DatetimeIndex
,类型(ts.val[0])
是一个numpy.float64
,应该是这样的。但是让我们介绍一种创造性的方法来标记NaN
:
ex2="""
Type: Some Metadata
User: More Metadata
Data:
01.10.1939 00:00:00 ; 1,1;
01.12.1939 00:00:00 ; NÄ ;
01.01.1940 00:00:00 ; 10 ;
"""
上面的ts=read_csv…
仍然可以正常工作,但是NÄ
会将val
列断开并将其转换为字符串。但是当我将此更改为
ts = pd.read_csv(io.StringIO(ex2), skiprows=4, decimal=',', sep=';',
index_col=0, usecols=[0,1], dayfirst=True,
parse_dates=True, names=['date', 'val'],
na_values='NÄ')
使用时,整个操作将失败。print(ts)
它不仅不接受NÄ
作为NaN
,还将所有val
s转换为字符串,从而忽略小数点逗号并保留尾随空格。ts.val[0]
现在是'1,1'
,因此简单的ts.val=ts.val.astype(float)
当然失败了
我在na_values='NÄ'
方面做错了什么?
为什么它还会打断decimal','
并添加空格?
似乎skipinitialspace=True
应该会有所帮助,但当然NÄ
仍然会打断val
列。
sep='\s*[;]s*'
似乎很有希望,而且
ts = pd.read_csv(io.StringIO(ex2), skiprows=4, decimal=',' ,sep='\s*[;]s*',
index_col=0, usecols=[0,1], dayfirst=True,
parse_dates=True, names=['date', 'val'],
na_values='NÄ')
提供了一个很好的打印(ts)
(注意小数点!),但现在我遇到了一个奇怪的情况,它确实替换了逗号,但是ts.val[0]
现在又是一个字符串,并且仍然有尾随空格('1.1'
)
那么我该如何读取这些文件呢?
我目前使用的解决方法是使用纯python读取CSV(我必须读取头文件(实际文件中有40行),然后将其写入正确的CSV,以便使用pandas读取:
file = open(myfile, 'r', encoding='UTF-8')
table = file.readlines()
file.close()
for v1 in range(0, len(table)):
table[v1] = table[v1].replace("NÄ", "NaN")
table[v1] = table[v1].replace(",", ".")
dataoutput = ["date;val\r\n"]
for v1 in range(3, len(table)):
dataoutput.append(table[v1])
f2 = open(myfile.replace('.csv', 'good.csv'), 'w')
for v1 in range(0, len(dataoutput)):
f2.write(dataoutput[v1])
f2.close()
ts = pd.read_csv(myfile.replace('.csv', 'good.csv'),
sep=';', usecols=[0, 1], index_col=0,
dayfirst=True, parse_dates=True)
ts.val = ts.val.astype(float)
但是,对于几千个CSV文件,大小高达1兆字节,这并不是一个真正的最佳解决方案,因此我想解决导入中的
NÄ
问题。您的sep
指定错误(它以s*
结尾,而不是\s*
,这意味着它要查找0到无限个s
字符)。这就是为什么您只捕获后面的前导空格,而不捕获后面的空格;
。顺便说一句,这也干扰了(1),因为您试图替换“NÄ”
,但值为“NÄ”
。请改用sep='\s*\\\s*'
将来可以做的一件事是自己打印出有问题的值,以确保它们包含它们认为您包含的内容,例如ts.iloc[1].val
此外,如果unicode中的NaN
值存在问题,则可以在解析之前将其剥离:
csv = io.StringIO(ex2.replace(u'N\xc4', '[MISSING]'))
ts = pd.read_csv(csv,
skiprows=4, decimal=',', index_col=0, usecols=[0,1],
dayfirst=True, parse_dates=True, names=['date', 'val'],
na_values='[MISSING]', sep='\s*\;\s*')
…这会给
val
date
1939-10-01 1.1
1939-12-01 NaN
1940-01-01 10.0
我可能错过了一些东西,但是可以在调用
read_csv()
时指定数据类型,或者在解析文件后转换值吗?可以将值指定为列表:na_values=['-1.#IND',1.#INF'];还可以检查尾随空格(检查我的示例)。dtype={'val':np.float64}
仅包含ValueError的错误:无法将列val转换为type
,并且在列表中设置NÄ
(naÄ值=['NÄ']]
)也不会改变结果。尾随(或前导)空格可能是一个问题。必须查看正则表达式的功能。将NÄ
设置为空格(naÄ值=''\s*[NÄ]\ s*
)似乎什么也没有改变。其他想法:检查编码。我对德语文件也有类似的问题。这是我完整的阅读行:df=pd.read_csv(join(path,filename),sep=';',encoding='iso-8859-1',engine='c',skiprows=[0],usecols=colstouse,na_values=['-1.#IND',1.#INF']
uex.replace在我没有使用StringIO
而是使用pd.read_csv('file.csv,skiprows=…
)执行示例时如何工作?csv=open('file.csv')。replace(u'N\xc4','missing]'
?结果是属性错误:“\u io.TextIOWrapper”对象对我来说没有属性“replace”
。“使用sep='\s*\\\s*'
而不是“该死,我可以发誓我总是在s
之前拥有\
。当然,搜索字母s没有意义。修复sep
有效,没有read().replace()。
val
date
1939-10-01 1.1
1939-12-01 NÄ
1940-01-01 10
file = open(myfile, 'r', encoding='UTF-8')
table = file.readlines()
file.close()
for v1 in range(0, len(table)):
table[v1] = table[v1].replace("NÄ", "NaN")
table[v1] = table[v1].replace(",", ".")
dataoutput = ["date;val\r\n"]
for v1 in range(3, len(table)):
dataoutput.append(table[v1])
f2 = open(myfile.replace('.csv', 'good.csv'), 'w')
for v1 in range(0, len(dataoutput)):
f2.write(dataoutput[v1])
f2.close()
ts = pd.read_csv(myfile.replace('.csv', 'good.csv'),
sep=';', usecols=[0, 1], index_col=0,
dayfirst=True, parse_dates=True)
ts.val = ts.val.astype(float)
csv = io.StringIO(ex2.replace(u'N\xc4', '[MISSING]'))
ts = pd.read_csv(csv,
skiprows=4, decimal=',', index_col=0, usecols=[0,1],
dayfirst=True, parse_dates=True, names=['date', 'val'],
na_values='[MISSING]', sep='\s*\;\s*')
val
date
1939-10-01 1.1
1939-12-01 NaN
1940-01-01 10.0