这是我要摆脱的情况:
我正在尝试阅读以下类型的csv:
para1,para2,para3,para4
1,2,3,4,
1,2,3,4,5,
1,2,3,4,
2,3,4,5,6,7,8,9,0,
我正在使用以下命令,并出现以下错误:
>>> import pandas as pd
>>> df =pd.read_csv("test.csv")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "C:\Python35\lib\site-packages\pandas\io\parsers.py", line 702, in parser_f
return _read(filepath_or_buffer, kwds)
File "C:\Python35\lib\site-packages\pandas\io\parsers.py", line 435, in _read
data = parser.read(nrows)
File "C:\Python35\lib\site-packages\pandas\io\parsers.py", line 1139, in read
ret = self._engine.read(nrows)
File "C:\Python35\lib\site-packages\pandas\io\parsers.py", line 1995, in read
data = self._reader.read(nrows)
File "pandas\_libs\parsers.pyx", line 899, in pandas._libs.parsers.TextReader.read
File "pandas\_libs\parsers.pyx", line 914, in pandas._libs.parsers.TextReader._read_low_memory
File "pandas\_libs\parsers.pyx", line 968, in pandas._libs.parsers.TextReader._read_rows
File "pandas\_libs\parsers.pyx", line 955, in pandas._libs.parsers.TextReader._tokenize_rows
File "pandas\_libs\parsers.pyx", line 2172, in pandas._libs.parsers.raise_parser_error
pandas.errors.ParserError: Error tokenizing data. C error: Expected 4 fields in line 3, saw 5
我试图搜索问题,并在SO上找到了该线程:
Python Pandas Error tokenizing data
所以,我尝试了。这不是我所期望的。它正在截断值。
>>> df =pd.read_csv("test.csv",error_bad_lines=False)
b'Skipping line 3: expected 4 fields, saw 5\nSkipping line 5: expected 4 fields, saw 9\n'
>>> df
para1 para2 para3 para4
0 1 2 3 4
1 1 2 3 4
我想要的是这样的东西:
如果有多余的值,则将这些列作为整数值,并在Extra中找到最高的列。然后将其余值设为零(0),直到最后一列,然后读取csv。
我期望的输出是这样的:
>>> df =pd.read_csv("test.csv")
>>> df
para1 para2 para3 para4 0 1 2 3 4
0 1 2 3 4 NaN NaN NaN NaN NaN
1 1 2 3 4 5.0 NaN NaN NaN NaN
2 1 2 3 4 NaN NaN NaN NaN NaN
3 2 3 4 5 6.0 7.0 8.0 9.0 0.0
>>> df = df.fillna(0)
>>> df
para1 para2 para3 para4 0 1 2 3 4
0 1 2 3 4 0.0 0.0 0.0 0.0 0.0
1 1 2 3 4 5.0 0.0 0.0 0.0 0.0
2 1 2 3 4 0.0 0.0 0.0 0.0 0.0
3 2 3 4 5 6.0 7.0 8.0 9.0 0.0
但是请注意,我不想照顾该专栏。相反,程序必须自动理解并按照上面的说明制作列标题。
第二,请尽量避免建议我写标题。由于可能有许多列,我可能无法写标题,而仅保留它。因此缺少的列标题将是如上所述的整数。有人对查询有任何解决方案吗,请让我知道?
答案 0 :(得分:3)
我不确定是否有更清洁的方法来执行此操作,但是我对其进行了测试,并且仅使用熊猫即可工作:
df = pd.read_csv('test.csv', header=None, sep='\n')
df= df[0].str.split(',', expand=True)
new_header = df.iloc[0].fillna(df.columns.to_series())
df = df[1:]
df.columns = new_header
答案 1 :(得分:2)
好吧,这意味着您必须解析文件直到其结束以获取实际的列数,因为pandas.read_csv
对此要求没有任何规定。
如果不考虑高性能(*),则一种简单的方法是依靠良好的旧csv模块并根据需要动态添加列:
with open('test.csv') as fd:
rd = csv.reader(fd)
header = next(rd) # initialize column names from first row
next_key = 0 # additional columns will start at '0'
data = {k: list() for k in header} # initialize data list per column
for row in rd:
while len(row) > len(header): # add eventual new columns
header.append(str(next_key))
data[header[-1]] = [np.nan] * len(data[header[0]])
next_key += 1 # increase next column name
# eventually extend the row up to the header size
row.extend([np.nan] * (len(header) - len(row)))
# and add data to the column lists
for i, k in enumerate(header): data[k].append(row[i])
# data is now in a dict format, suitable to feed DataFrame
df = pd.DataFrame(data)
(*)代码效率不高,因为它一次将元素添加到列表中。这对于pandas DataFrame来说将是可怕的,即使对于Python列表也不是很好。可以通过在numpy.ndarray
中分配束来改善它,但是代价是增加复杂性。
答案 2 :(得分:1)
尝试使用以下代码,先使用sep=' '
,然后使用iloc
,它会获得第一列,然后依次是str.split
和expand=True
,这将创建一个新的数据帧,然后fillna
替换NaN
,然后最后一行是用list
理解和list(range(...))
来命名列。
因此您应该使用:
df = pd.read_csv("test.csv", sep=' ')
df2 = df.iloc[:, 0].str.replace(',$', '').str.split(',', expand=True).fillna(0)
dd = df.columns[0].split(',')
ff = [str(x) for x in range(len(df2.columns) - len(dd))]
df2.columns = dd + ff
print(df2)