消除CSV fi中不需要的换行符

2024-05-23 21:52:36 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个非常大的CSV文件(百万+行),我想在上面执行一些操作。问题是,有些行有一些不需要的换行符,如下所示:

New York City; Iron Man; no superpowers;
Metropolis; Superman; superpowers;
New York City;
Spider-Man;
superpowers;
Gotham; Batman; no superpowers;
New York City; Doctor Strange; superpowers;

因此,该文件有三列(locationsuperherosuperpowers)。由于Spider Man的条目是错误的,因为它的条目之间有换行符,pandas错误地假设这是三个独立的行,即第二列和第三列中的NaNs。你知道吗

我的想法是在使用regex导入时解决这个问题。根据this website,这个正则表达式正确地匹配所需的行,而不匹配错误的行(即Spider Man)。你知道吗

(.*[;].*[;].*)

但是,它的逆((?!(.*[;].*[;].*)))不起作用,因为它不仅不匹配三个错误行,而且不匹配每个正常行的第三个条目。你知道吗

我的另一种方法是简单地设置列数,然后从整个文件中删除所有换行符。不过,这也不管用。你知道吗

superhero_df = pd.read_csv("superheroes.csv", sep=' *; *', skiprows=12, names=["location", "superhero", "superpower"], index_col=False, engine="python")
superhero_df = superhero_df.replace('\r\n','', regex=True)

所需的输出应如下所示:

New York City; Iron Man; no superpowers
Metropolis; Superman; superpowers;
New York City; Spider-Man; superpowers;
Gotham; Batman; no superpowers;
New York City; Doctor Strange; superpowers;

Tags: 文件nocitydfnew错误条目spider
3条回答

下面的正则表达式在每三个字段之后消除不需要的换行符和其他空格。它假定字段没有任何内部分号:

print(re.sub(r'([^;]*);\s*([^;]*);\s*([^;]*);\s+', r'\1;\2;\3\n', 
      line, flags=re.M))
#New York City; Iron Man;no superpowers
#Metropolis;Superman;superpowers
#New York City;Spider-Man;superpowers
#Gotham;Batman;no superpowers
#New York City;Doctor Strange;superpowers

在使用Pandas之前,可以在循环中运行它来预处理文件。你知道吗

如果我是你,我会在一个新的文本文件中重写整个数据,只需对源文本文件进行简单的迭代,然后将结果文件加载到Pandas中,无需re

with open('source.txt') as fin, open('target.txt', 'w') as fout:
    lc = 0
    for line in fin:
        lc += line.count(';')
        if  lc < 3:
            fout.write(line[:-1])
        else:
            fout.write(line)
            lc = 0

结果:

# New York City; Iron Man; no superpowers;
# Metropolis; Superman; superpowers;
# New York City;Spider-Man;superpowers;
# Gotham; Batman; no superpowers;
# New York City; Doctor Strange; superpowers;

解读熊猫:

pd.read_csv('target.txt', header=None, sep=';', usecols=range(3))

#                0                1                2
# 0  New York City         Iron Man   no superpowers
# 1     Metropolis         Superman      superpowers
# 2  New York City       Spider-Man      superpowers
# 3         Gotham           Batman   no superpowers
# 4  New York City   Doctor Strange      superpowers

注意:usecols是唯一需要的,因为后面有分号。通过使用导入可以避免这种情况

with open('source.txt') as fin, open('target.txt', 'w') as fout:
    lc = 0
    for line in fin:
        lc += line.count(';')
        if  lc < 3:
            fout.write(line.strip())
        else:
            fout.write(line.strip()[:-1] + '\n')
            lc = 0

解读熊猫:

pd.read_csv('target.txt', header=None, sep=';')

#                0                1                2
# 0  New York City         Iron Man   no superpowers
# 1     Metropolis         Superman      superpowers
# 2  New York City       Spider-Man      superpowers
# 3         Gotham           Batman   no superpowers
# 4  New York City   Doctor Strange      superpowers

那怎么办:

^([^;]+);[\r\n]*([^;]+);[\r\n]*([^;]+);

替换为:

\1;\2;\3;

regex101

run here

import re

regex = r"^([^;]+);[\r\n]*([^;]+);[\r\n]*([^;]+);"

test_str = ("New York City; Iron Man; no superpowers;\n"
    "Metropolis; Superman; superpowers;\n"
    "New York City;\n"
    "Spider-Man;\n"
    "superpowers;\n"
    "Gotham; Batman; no superpowers;\n"
    "New York City; Doctor Strange; superpowers;\n\n")

subst = "\\1;\\2;\\3;"

# You can manually specify the number of replacements by changing the 4th argument
result = re.sub(regex, subst, test_str, 0, re.MULTILINE | re.DOTALL)

if result:
    print (result)

相关问题 更多 >