我正在通过编写一些简单的程序来学习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{赋值} catch {移动到下一个团队}机制。
有人可以提供任何反馈/建议吗?
谢谢!
编辑:
下面的 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 名玩家...
知道我的逻辑错误可能是什么吗?
最佳答案
嗯,这是一个 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)
关于python - 处理 Python 中的越界/写入 CSV,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42442955/