csv 列值转到新行导致加载错误 pandas
csv column values going to new line causing errors loading in pandas
我对 csv 有问题,它在一个列中有一个拆分,转到一个新行。我可以手动编辑 .csv 文件来解决这个问题,但是有 ~200 个文件。
数据集包含更多列并且可以包含空值,但最后一列始终有一个值。该问题每次也只发生在同一列中。所以我想找到最后一个值何时为空,然后尝试用 .shift() 填充这些值,但希望有一种更简单的方法。
在vscode
中查看
orderid,fruit,count,person
3523,apple,84,peter
2522,green
grape, 99, mary
1299, watermelon, 93, paul
pandas read_csv
orderid fruit count person
3523 apple 84 peter
2522 green NaN NaN
grape 99 mary NaN
1299 watermelon 93 paul
想要的栏目
orderid fruit count person
3523 apple 84 peter
2522 green grape 99 mary
1299 watermelon 93 paul
修复您的文件:
- 使用
m = re.findall('(?<=[a-zA-Z])\s+\n[a-zA-Z]', text)
查找类似 ,green \ngrape
的案例
- 该模式将找到
alpha \nalpha
并忽略 alpha \nnumeric
m
将是所有匹配项的列表(例如 [' \ng']
)
.replace(' \ng', ' g')
,结果为 ,green grape
- 找到所有
pathlib
的文件
.rglob
查找所有子目录。如果所有文件都在一个目录中,则使用 .glob
pathlib
将路径视为对象而不是字符串。因此,pathlib
个对象有很多方法。
.stem
returns 文件名
.suffix
returns 文件扩展名(例如 .csv
)
- 这不会覆盖您现有的文件。它将创建一个新文件,将
_fixed
添加到名称中。
import re
from pathlib import Path
# list of all the files
files = list(Path(r'c:\some_path').rglob('*.csv'))
# iterate through each file
for file in files:
# create new filename name_fixed
new_file = file.with_name(f'{file.stem}_fixed{file.suffix}')
# read all the text in as a string
text = file.read_text()
# find and fix the sections that need fixing
m = re.findall('(?<=[a-zA-Z])\s+\n[a-zA-Z]', text)
for match in m:
text = text.replace(match, f' {match[-1:]}')
text_list = text.split('\n')
text_list = [x.strip() for x in text_list]
# write the new file
with new_file.open('w', newline='') as f:
w = csv.writer(f, delimiter=',')
w.writerows([x.split(',') for x in text_list])
示例:
在.csv
中包含以下内容:
orderid,fruit,count,person
3523,apple,84,peter
2522,green
grape, 99, mary
1299, watermelon, 93, paul
3523,apple,84,peter
2522,green
banana, 99, mary
1299, watermelon, 93, paul
3523,apple,84,peter
2522,green
apple, 99, mary
1299, watermelon, 93, paul
新文件:
orderid,fruit,count,person
3523,apple,84,peter
2522,green grape, 99, mary
1299, watermelon, 93, paul
3523,apple,84,peter
2522,green banana, 99, mary
1299, watermelon, 93, paul
3523,apple,84,peter
2522,green apple, 99, mary
1299, watermelon, 93, paul
创建数据框:
import pandas as pd
new_files = list(Path(f'c:\some_path').glob('*_fixed.csv'))
df = pd.concat([pd.read_csv(f) for f in new_files])
解决方案
这是另一个解决方案:
一个。这里的逻辑是首先找到以 4 位数字开头的行。
乙。一旦确定了行,任何行(除了最上面的行:header 行)
- 没有 4 位数字开头且
- 无三隔
','
,
将附加到上一行。
摄氏度。最后,任何白色的 space 将被丢弃在一行的末尾,所有的行被放在一起形成一个字符串,如果 he/she 愿意,用户可以将其写入 .csv 文件。
D.我们使用 io.StringIO
作为数据框加载此字符串。
示例 1
import pandas as pd
from io import StringIO
import re
def get_clean_data(lines):
target_lines = [re.findall('^\d{4}', line) for line in lines]
target_lines_dict = dict((i, val[0]) if (len(val)>0) else (i, None) for i,val in enumerate(target_lines))
correct_lines = list()
line_index = 0
for i,line in enumerate(lines):
if i==0:
correct_lines.append(line.strip())
if i>0:
if target_lines_dict[i] is not None:
correct_lines.append(line.strip())
line_index +=1
else:
correct_lines[line_index] += ' ' + line.strip()
correct_lines = [re.sub(',\s*', ', ', line)+'\n' for line in correct_lines]
ss = ''.join(correct_lines)
return ss
# Dummy Data
s = """
orderid,fruit,count,person
3523,apple,84,peter
2522,green
grape, 99, mary
1299, watermelon, 93, paul
"""
lines = s.strip().split('\n')
# In case of a csv file, use readlines:
# with open('csv_file.csv', 'r') as f:
# lines = f.readlines()
# Get cleaned data
ss = get_clean_data(lines)
# Make Dataframe
df = pd.read_csv(StringIO(ss), sep=',')
print(df)
输出:
orderid fruit count person
0 3523 apple 84 peter
1 2522 green grape 99 mary
2 1299 watermelon 93 paul
示例 2
现在让我们使用以下虚拟数据。
s = """
orderid,fruit,count,person
3523,apple,84,peter
2522,green
grape, 99, mary
1299, watermelon, 93, paul
3523,apple,84,peter
2522,green
banana, 99, mary
1299, watermelon, 93, paul
3523,apple,84,peter
2522,green
apple, 99, mary
1299, watermelon, 93, paul
"""
输出:
orderid fruit count person
0 3523 apple 84 peter
1 2522 green grape 99 mary
2 1299 watermelon 93 paul
3 3523 apple 84 peter
4 2522 green banana 99 mary
5 1299 watermelon 93 paul
6 3523 apple 84 peter
7 2522 green apple 99 mary
8 1299 watermelon 93 paul
我对 csv 有问题,它在一个列中有一个拆分,转到一个新行。我可以手动编辑 .csv 文件来解决这个问题,但是有 ~200 个文件。
数据集包含更多列并且可以包含空值,但最后一列始终有一个值。该问题每次也只发生在同一列中。所以我想找到最后一个值何时为空,然后尝试用 .shift() 填充这些值,但希望有一种更简单的方法。
在vscode
中查看orderid,fruit,count,person
3523,apple,84,peter
2522,green
grape, 99, mary
1299, watermelon, 93, paul
pandas read_csv
orderid fruit count person
3523 apple 84 peter
2522 green NaN NaN
grape 99 mary NaN
1299 watermelon 93 paul
想要的栏目
orderid fruit count person
3523 apple 84 peter
2522 green grape 99 mary
1299 watermelon 93 paul
修复您的文件:
- 使用
m = re.findall('(?<=[a-zA-Z])\s+\n[a-zA-Z]', text)
查找类似,green \ngrape
的案例- 该模式将找到
alpha \nalpha
并忽略alpha \nnumeric
m
将是所有匹配项的列表(例如[' \ng']
).replace(' \ng', ' g')
,结果为,green grape
- 该模式将找到
- 找到所有
pathlib
的文件.rglob
查找所有子目录。如果所有文件都在一个目录中,则使用.glob
pathlib
将路径视为对象而不是字符串。因此,pathlib
个对象有很多方法。.stem
returns 文件名.suffix
returns 文件扩展名(例如.csv
)
- 这不会覆盖您现有的文件。它将创建一个新文件,将
_fixed
添加到名称中。
import re
from pathlib import Path
# list of all the files
files = list(Path(r'c:\some_path').rglob('*.csv'))
# iterate through each file
for file in files:
# create new filename name_fixed
new_file = file.with_name(f'{file.stem}_fixed{file.suffix}')
# read all the text in as a string
text = file.read_text()
# find and fix the sections that need fixing
m = re.findall('(?<=[a-zA-Z])\s+\n[a-zA-Z]', text)
for match in m:
text = text.replace(match, f' {match[-1:]}')
text_list = text.split('\n')
text_list = [x.strip() for x in text_list]
# write the new file
with new_file.open('w', newline='') as f:
w = csv.writer(f, delimiter=',')
w.writerows([x.split(',') for x in text_list])
示例:
在.csv
中包含以下内容:
orderid,fruit,count,person
3523,apple,84,peter
2522,green
grape, 99, mary
1299, watermelon, 93, paul
3523,apple,84,peter
2522,green
banana, 99, mary
1299, watermelon, 93, paul
3523,apple,84,peter
2522,green
apple, 99, mary
1299, watermelon, 93, paul
新文件:
orderid,fruit,count,person
3523,apple,84,peter
2522,green grape, 99, mary
1299, watermelon, 93, paul
3523,apple,84,peter
2522,green banana, 99, mary
1299, watermelon, 93, paul
3523,apple,84,peter
2522,green apple, 99, mary
1299, watermelon, 93, paul
创建数据框:
import pandas as pd
new_files = list(Path(f'c:\some_path').glob('*_fixed.csv'))
df = pd.concat([pd.read_csv(f) for f in new_files])
解决方案
这是另一个解决方案:
一个。这里的逻辑是首先找到以 4 位数字开头的行。
乙。一旦确定了行,任何行(除了最上面的行:header 行)
- 没有 4 位数字开头且
- 无三隔
','
,
将附加到上一行。
摄氏度。最后,任何白色的 space 将被丢弃在一行的末尾,所有的行被放在一起形成一个字符串,如果 he/she 愿意,用户可以将其写入 .csv 文件。
D.我们使用 io.StringIO
作为数据框加载此字符串。
示例 1
import pandas as pd
from io import StringIO
import re
def get_clean_data(lines):
target_lines = [re.findall('^\d{4}', line) for line in lines]
target_lines_dict = dict((i, val[0]) if (len(val)>0) else (i, None) for i,val in enumerate(target_lines))
correct_lines = list()
line_index = 0
for i,line in enumerate(lines):
if i==0:
correct_lines.append(line.strip())
if i>0:
if target_lines_dict[i] is not None:
correct_lines.append(line.strip())
line_index +=1
else:
correct_lines[line_index] += ' ' + line.strip()
correct_lines = [re.sub(',\s*', ', ', line)+'\n' for line in correct_lines]
ss = ''.join(correct_lines)
return ss
# Dummy Data
s = """
orderid,fruit,count,person
3523,apple,84,peter
2522,green
grape, 99, mary
1299, watermelon, 93, paul
"""
lines = s.strip().split('\n')
# In case of a csv file, use readlines:
# with open('csv_file.csv', 'r') as f:
# lines = f.readlines()
# Get cleaned data
ss = get_clean_data(lines)
# Make Dataframe
df = pd.read_csv(StringIO(ss), sep=',')
print(df)
输出:
orderid fruit count person
0 3523 apple 84 peter
1 2522 green grape 99 mary
2 1299 watermelon 93 paul
示例 2
现在让我们使用以下虚拟数据。
s = """
orderid,fruit,count,person
3523,apple,84,peter
2522,green
grape, 99, mary
1299, watermelon, 93, paul
3523,apple,84,peter
2522,green
banana, 99, mary
1299, watermelon, 93, paul
3523,apple,84,peter
2522,green
apple, 99, mary
1299, watermelon, 93, paul
"""
输出:
orderid fruit count person
0 3523 apple 84 peter
1 2522 green grape 99 mary
2 1299 watermelon 93 paul
3 3523 apple 84 peter
4 2522 green banana 99 mary
5 1299 watermelon 93 paul
6 3523 apple 84 peter
7 2522 green apple 99 mary
8 1299 watermelon 93 paul