尝试按百分比拆分列表

7 投票
1 回答
11826 浏览
提问于 2025-04-18 04:16

我正在尝试通过输入一个百分比,把一个列表分成两个其他列表,随机从主列表中抓取元素。训练集就是剩下的列表。当我生成一个随机索引来选择元素时,我遇到了问题。这段代码在小列表上能正常工作,但当我处理长度为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。显然你不会真的达到那个点,但希望这样能让你明白问题所在。

撰写回答