【问题标题】:CSV text clean up and comparing in Python在 Python 中清理和比较 CSV 文本
【发布时间】:2017-09-20 02:15:44
【问题描述】:

感谢阅读!我对此很陌生,但昨天我开始从网站中提取数据(商品名称及其相应的价格),并弄清楚如何使用 Python 2.7 为给定网站创建格式为:价格、商品名称的 csv 文件。现在我有一些数据集,我想比较它们并获得给定项目名称的平均价格。我现在遇到的问题是每个网站上的项目名称(可能)略有不同。例如我的第一个数据集给出了 csv 文件

4.0, Jungle Book
5.0, "Peter Pan"
4.0, Lady and the Tramp

第二个给出

5.0, Disney's Jungle Book
6.0, Disney's Up
4.0, Disney's Peter Pan

第三个给出

5.0, Up (DVD)
4.0, Peter pan (DVD)
6.0, "Lady and the Tramp" (DVD)

最后我想要一个平均输出文件,例如

4.5, Jungle Book
5.0, Lady and the Tramp
4.33, Peter Pan
5.5, Up

我的第一个问题是删除 csv 文件中的特殊字符,例如“或某些单词(例如“Disney's”、“(DVD)”)。我找到了有关从 csv 文件中删除行和列的信息,但我很难时间在这些元素中进行编辑。像这样删除“(DVD)”类型的作品,但使我的 csv 文件更加混乱,包含更多“和 [ 字符..

import csv
import string

input_file = open('DesktopData.csv', 'r')
output_file = open('fixformat.csv', 'w')
data = csv.reader(input_file)
writer = csv.writer(output_file,quoting=csv.QUOTE_ALL)# dialect='excel')
specials = '(DVD)'

for line in data:
    line = str(line)
    new_line = str.replace(line,specials,'')
    writer.writerow(new_line.split(','))

input_file.close()
output_file.close()

一旦可行,我想采用给定标题的平均价格。我有一些想法,但缺乏真正弄清楚的python语法

Read all titles and put in mainlist;
 if title already exsists, ignore/dont make new row with title
Read all files and compare with mainlist;
 if title is found, put corresponding price in new column behind title

在我的脑海中,这必须输出

Jungle Book, 4.0, 5.0
Lady and the Tramp, 4.0, 6.0
Peter Pan, 5.0, 4.0, 4.0
Up, 6.0, 5.0

一旦我得到这个,我很确定我可以把它变成普通的 csv 文件。任何建议都非常感谢!

【问题讨论】:

  • 您可能想看看导入 pandas 并尝试一下。从查看 pd.read_csv() 方法开始。

标签: python csv web-scraping


【解决方案1】:

到目前为止,最难的部分是找出相同的名称,但有细微的差别。在这里的解决方案中,我做了一个简单的normalize_titlefunction,但它远非完美。我想它需要为每个新数据集手动调整和扩展。但是,除此之外,这里有一个解决您的问题的方法,它从几个 csv 文件中收集数据,然后将平均成本与电影标题一起存储在一个新的 csv 文件中:

import csv

filenames = ['first.csv', 'second.csv', 'third.csv']
outfile = 'avg.csv'

removables = ['[', ']', '"', "'", "Disney's", '(DVD)']
def nomalize_title(title):
    for remove in removables:
        title = title.replace(remove, '')
    title = title.lower() # Correct capitalization is HARD
    return title

moviecosts = dict()
for filename in filenames:
    with open(filename, 'rb') as f:
        reader = csv.reader(f)
        for row in reader:
            raw_title = row[1]
            title = normalize_title(raw_title)
            price = float(row[0])

            if not moviecosts.has_key(title):
                moviecosts[title] = []

            moviecosts[title].append(price)

with open(outfile, 'wb') as f:
    writer = csv.writer(f)
    for movie in moviecosts:
        avg_cost = sum(moviecosts[movie])/len(moviecosts[movie])
        row = [avg_cost, movie]
        writer.writerow(row)

可以看出,我将不同的成本存储到列表字典中。对我来说,这似乎是解决当前问题的最自然的数据结构。

【讨论】:

  • 感谢您的宝贵时间,我刚刚运行它,目前它在 1 个单元格中为我提供了 1 个值的输出,这是数据库中所有 dvd 的总体平均值,但这绝对有帮助。我找不到标准化后的标题列表;如在哪里可以找到“电影”中的标题?
  • 如果你只得到一个平均值,这意味着所有标题都被“标准化”为同一个字符串。如果你打印moviecosts dict,你有什么
  • 如果我打印moviecosts,它会显示{None: [4.0, 12.0, ...., 22.0]} 所以没有保存任何标题?在变量资源管理器中,我可以看到 raw_title 上升到最后一个数据库的最后一个标题。所有的数据库价格都在moviecosts
  • 啊,我的错。我忘记在规范化文件名的函数中添加 return 语句。这将使 python 默认返回None。试试我刚刚添加的更新。希望效果更好。
  • 规范化现在工作正常,很好!然而,输出只给出最后一个 csv 文件输入,而不用第一个和第二个计算。但是,我看到它的平均工作正常,因为在最后一个数据库中存在给定标题的一些重复项
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-10-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多