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