尝试按百分比拆分列表
我正在尝试通过输入一个百分比,把一个列表分成两个其他列表,随机从主列表中抓取元素。训练集就是剩下的列表。当我生成一个随机索引来选择元素时,我遇到了问题。这段代码在小列表上能正常工作,但当我处理长度为1000的列表时,就不行了。
错误信息:
File "/Applications/WingIDE.app/Contents/MacOS/src/debug/tserver/_sandbox.py", line 1, in <module>
# Used internally for debug sandbox under external interpreter
File "/Applications/WingIDE.app/Contents/MacOS/src/debug/tserver/_sandbox.py", line 29, in partitionRankings
File "/Users/rderickson9/anaconda/lib/python2.7/random.py", line 241, in randint
return self.randrange(a, b+1)
File "/Users/rderickson9/anaconda/lib/python2.7/random.py", line 217, in randrange
raise ValueError, "empty range for randrange() (%d,%d, %d)" % (istart, istop, width)
ValueError: empty range for randrange() (0,0, 0)
raw Ratings 是一个列表,而 testPercent 是一个浮点数。
举个例子:
rawRatings = [(123,432,4),(23,342,3),(23,123,5),(234,523,3),(34,23,1), (12,32,4)]
testPercent = .2
partitionRankings(rawRatings, testPercent)
[(23,123,5),(234,523,3),(34,23,1),(123,432,4),(12,32,4)],[(23,342,3)]
def partitionRankings(rawRatings, testPercent):
testSet = []
trainingSet = []
howManyNumbers = int(round(testPercent*len(rawRatings)))
declineRandom = 0
while True:
if declineRandom == howManyNumbers:
break
randomIndex = random.randint(0, (len(rawRatings)-1)-declineRandom)
testSetTuple = rawRatings[randomIndex]
del rawRatings[randomIndex]
testSet.append(testSetTuple)
declineRandom = declineRandom + 1
trainingSet = rawRatings[:]
return (trainingSet), (testSet)
我不想选择相同的随机索引。一旦我选择了一个,就不想再随机选择它。我觉得这样做不太对。这就是我遇到麻烦的地方。
randomIndex = random.randint(0, (len(rawRatings)-1)-declineRandom)
1 个回答
14
因为训练集的顺序并不重要,你可以用一种完全不同的方法来处理这个问题——把原始评分的列表打乱,然后取前面 howManyNumbers
个元素作为你的测试集,其余的作为训练集。
import random
def partitionRankings(rawRatings, testPercent):
howManyNumbers = int(round(testPercent*len(rawRatings)))
shuffled = rawRatings[:]
random.shuffle(shuffled)
return shuffled[howManyNumbers:], shuffled[:howManyNumbers]
至于为什么你的代码不工作,问题就出在你猜的那一行:
randomIndex = random.randint(0, (len(rawRatings)-1)-declineRandom)
问题出在 -declineRandom
上。
- 每次你循环的时候,你都会移除你选中的那个条目,所以即使你再次得到相同的索引,你也不会选到同一个元素。
- 如果你在每次循环中不移除列表中的元素,这样的话就会导致你可能会选到同一个元素两次——这只是防止你选到最后
declineRandom
个元素中的任何一个。- 你需要在每次循环中把元素移动到列表的末尾。
- 因为你删除了元素而且没有在列表末尾替换它们,
len(rawRatings)
的长度就会变小,而declineRandom
的值会变大。- 假设你有一个包含1000个项目的列表,想把600个放到测试集中,当你在测试集中有550个项目时,你会试图得到一个随机整数,这个整数应该大于等于零并且小于等于
(450-1)-550=-101
。显然你不会真的达到那个点,但希望这样能让你明白问题所在。
- 假设你有一个包含1000个项目的列表,想把600个放到测试集中,当你在测试集中有550个项目时,你会试图得到一个随机整数,这个整数应该大于等于零并且小于等于