【问题标题】:Handling out of bounds in Python/writing to CSV在 Python 中处理越界/写入 CSV
【发布时间】:2017-02-24 15:54:50
【问题描述】:

我正在通过编写一些简单的程序来学习 Python。我正在尝试执行以下操作 -

我有一个 xlsx。格式如下:

Team, Player

我想做的是对现场团队应用过滤器,然后从每个团队中随机抽取 3 名球员。

例如,我的 XLS 看起来像:

Man Utd, Ryan Giggs
Man Utd, Paul Scholes
Man Utd, Paul Ince
Man Utd, Danny Pugh
Liverpool, Steven Gerrard
Liverpool, Kenny Dalglish
... 

我想最终得到一个由每支球队的 3 名随机球员组成的 XLS,在少于 3 名的情况下只有 1/2(这就是我正在努力解决的问题)。

我是这样开始的:

import xlrd, random, csv

# First open the workbook
wb = xlrd.open_workbook('C:\\Users\\ADMIN\\Desktop\\1.xlsx')

# Then select the sheet. 
sheet = wb.sheet_by_name('Sheet1')

# Then get values of each column. Excuse first item which is header
teams = sheet.col_values(0)[1:]
players = sheet.col_values(1)[1:]
filtered_teams = filter(lambda x: x[0] > 2, zip(teams, players))

teams = {}
for t,p in zip(teams,players):
    if t in teams:
        teams[t].append(p)
    else:
        teams[t] = [p]


samples = [teams[t] + random.sample(teams[t],3) for t in teams]
myFile = open('C:\\Users\\ADMIN\\Desktop\\1.csv', 'wb')
wr = csv.writer(myFile, quoting=csv.QUOTE_ALL)
wr.writerow(samples)

我遇到的问题 -

    wr.writerow(samples)
TypeError: a bytes-like object is required, not 'str'

我需要在这里做一些明确的演员吗?我该如何解决这个问题?

另外,在创建样本时,如果我使用所有球队/球员的列表:

samples = [teams[t] + random.sample(teams[t],1) for t in teams]

它会起作用,但如果我使用:

samples = [teams[t] + random.sample(teams[t],3) for t in teams]

我得到了一个出界异常,因为有些球队没有 3 名球员与他们相关联(只有 1 名)。确切地说,我得到:

    raise ValueError("Sample larger than population or is negative")
ValueError: Sample larger than population or is negative

(我简单的 Java 大脑将其理解为 OOB)。

此时我该如何解决这个问题/只是让它转移到下一个团队?某种 try{assignment} catch{move to next team} 机制。

任何人都可以提供任何反馈/建议吗?

谢谢!

编辑:

下面的 Jean-François Fabre 解决了抛出的错误,非常感谢。但是,现在,当我写入 CSV 时,它只返回 17 行(应该有数百行),而且格式完全错误......我希望写类似:

Man Utd, Ryan Giggs
Man Utd, Paul Scholes
Man Utd, Danny Pugh
Liverpool, Steven Gerrard
Liverpool, Kenny Dalglish

但似乎只是玩家被退回,没有任何真正的订购?确实,如果我将其更改为 random.sample(teams[t],min(2,len(teams[t])) 我仍然有每支球队返回 5/6 名球员......

知道我的逻辑错误可能在这里吗?

【问题讨论】:

  • @SergeBallesta 我不认为我是,我只是想打印到 CSV :)

标签: python python-3.x csv xls


【解决方案1】:

嗯,这是一个 2(现在 3 :))问题合二为一。既然我有所有的答案,我会跳进去:

myFile = open('C:\\Users\\ADMIN\\Desktop\\1.csv', 'wb')

仅适用于 Python 2。对于 Python 3,您必须以文本模式打开(并且可能必须添加 newline="" 以避免虚假的行空白:

myFile = open('C:\\Users\\ADMIN\\Desktop\\1.csv', 'w', newline="")

对于您的其他问题,只需更改:

random.sample(teams[t],3)

进入

random.sample(teams[t],min(3,len(teams[t]))

所以你总是在界限之内。

现在,关于已删除的输出,您正在创建一个列表列表,但您只使用writerow 写入一行。起初这让我感到震惊,但后来我忘记了 :) 改用 writerows,否则你只会得到一行列表表示为字符串,带有括号、逗号...

最后一个问题:文件中缺少球队信息,因为您只生成球员姓名。

总而言之,我会像这样重写整个内容并进行一些改进:

samples = [[team] + players + random.sample(players,min(3,len(players)) for team,players in teams.items()]
with open(r'C:\Users\ADMIN\Desktop\1.csv', 'w', newline='') as myFile:
   wr = csv.writer(myFile, quoting=csv.QUOTE_ALL)
   wr.writerows(samples)

【讨论】:

  • @JeanFrançoisFabre 非常感谢您的回复。这解决了编译器的所有错误,因此程序运行......但结果出乎意料。我只有 17 行,每行有数百列,而且它们似乎没有以任何方式组织。知道可能是什么原因造成的吗?我会更新问题。
  • 哦,我明白了,我认为您需要writerows 而不是writerow。试试看,我会相应地编辑我的答案。已编辑,我确定这是问题所在。
  • 但是,与您的预期输出相比,我不确定:您总是首先需要团队名称,但您从未在 samples 中输出它。也许我们应该将键添加到值中。您提到的预期输出是每行的“团队名称,球员”,这对于当前的random.sample 是不可能的,它发出 4 个以上的球员......所以似乎还有其他问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-09-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多