【问题标题】:Replace a pattern in CSV file Python替换 CSV 文件 Python 中的模式
【发布时间】:2015-01-16 00:48:10
【问题描述】:

我有多个 CSV 文件,它们可以以多种方式表示相似的事物。例如,15 年可以写成 age: 15, age (years): 15, age: 15 岁(这些都是我目前看到的模式)。我想用 15 年替换所有这些。当我知道实际年龄或列号时,我知道该怎么做,但是每次出现的年龄肯定不同,并且列不固定。 csv 文件可能如下所示:

CSV1:

h1,h2,h3
A1,age:15,hh
B3,age:10,fg

所需的 CSV1

h1,h2,h3
A1,15 years,hh
B3,10 years,fg

当它的正确年龄:15 岁时,它肯定是年,而不是月或任何其他单位。

【问题讨论】:

  • 对于年龄字段,数字就足够了吗?如果是这样,您可以使用str.translae 方法。创建一个将字母映射到空字符串的表。一个例子是here
  • @b10n:这听起来是个好主意......除了你遗漏了很多细节 - 所以我建议你发布一个包含一些实际代码的答案。
  • @dan:您建议如何确定要修复的列?
  • @martineau 如果您是指要使用文件中的哪一列,坦率地说我没有答案,因为我有多个文件,每个文件都由来自世界各地的研究人员处理.所以格式不一样。
  • @b10n 我需要在数字后面加上“年”。

标签: python regex csv replace


【解决方案1】:

使用re.sub,如下所示,

re.sub(r'(,|^)(?:age\s*(?:\(years\))?:\s*(\d+)\s*(?:years)?)(?=,|$)',
       r'\1\2 years', string)

DEMO

例子:

import re
import csv
with open('file') as f:
    reader = csv.reader(f)
    for i in reader:
        print(re.sub(r'(,|^)(?:age\s*(?:\(years\))?:\s*(\d+)\s*(?:years)?)(?=,|$)', r'\1\2 years', ','.join(i)))

输出:

h1,h2,h3
A1,15 years,hh
B3,10 years,fg

for i in reader:
    print(re.sub(r'(,|^)[^,\n]*age\s*:[^,\n]*\b(\d+)\b[^,\n]*', r'\1\2 years', ','.join(i)))

【讨论】:

  • 我认为不需要那么复杂。 re.sub(r'age.*?: (\d{1,2})[^,]*', r'\1 years', text)
  • 我做了一个正则表达式来满足这些age: 15, age (years): 15, age: 15 years 条件。
  • @AvinashRaj 谢谢。我会尝试并更新你。
  • 是的,但是长的正则表达式很难调试。 regex101.com/r/hK1uH1/5
【解决方案2】:

使用字符串模块中的翻译表方法。

import csv
from string import maketrans
from string import ascii_uppercase, ascii_lowercase
delete = ascii_uppercase + ascii_lowercase + ":"
tran = maketrans("", "")

with open("infile.csv", "rb") as infile, open("output.csv", "wb") as outfile:
    reader = csv.reader(infile)
    writer = csv.writer(outfile)
    for row in reader:
        #assuming the second field here
        row[1] = row[1].translate(tran, delete) + " years"
        writer.writerow(row)

我通常更喜欢string.translate,而不是适用的正则表达式,因为它更容易理解和调试。

【讨论】:

  • @martineau 感谢您对翻译的关注。你是对的。
【解决方案3】:

这是一个猜谜游戏,但如果规则是您想要转换任何包含“年份”一词和一些十进制数字的东西,这应该可以。

import re

_is_age_search = re.compile(r"year|age", re.IGNORECASE).search
_find_num_search = re.compile(r"(\d+)").search

outdir = '/some/dir'
for filename in csv_filenames:
    with open(filename) as f_in, open(os.path.join(outdir, filename), 'w') as f_out:
        writer = csv.writer(f_out)
        for row in csv.reader(f_in):
            for i, val in enumerate(row):
                if _is_age_search(val):
                    search = _find_num_search(val)
                    if search:
                        row[i] = "%d years" % search.groups()
            writer.writerow(row)

【讨论】:

  • 谢谢。只是“年”这个词可能存在也可能不存在。不过,我可以试试“年龄”这个词。
  • @dan - 你是对的。添加了一个可以进行多个字符串比较的正则表达式搜索。
猜你喜欢
  • 2013-06-20
  • 2014-01-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-05-14
  • 1970-01-01
相关资源
最近更新 更多