【问题标题】:Python: Given a group of strings uniformly bucket them into k buckets so that same strings go to the same bucketPython:给定一组字符串,将它们统一分桶到 k 个桶中,以便相同的字符串进入同一个桶
【发布时间】:2017-08-29 06:37:59
【问题描述】:

我有一组(2000 个)行,每行有很多元素。一行中的一个元素是一个字符串(“名称”),每组 5 行是通用的(唯一名称的总数为 500)。 我希望具有相同“名称”的行最终位于同一个存储桶中。所以函数应该总是为给定的输入返回相同的值。

我想将它用于 k 折交叉验证,因此我需要创建 k 个存储桶,其元素数量尽可能均匀分布,+/- 少数元素可以,但超过 10% 则不行。

对于 k = 10,我应该有 10 个桶,每个桶有 200 个元素,190 或 210 可以,但 250 和 180 不行。我尝试了this answer,但它并没有给我一个非常统一的结果。这可能是由于数据集本身造成的,但如果每个桶的元素数量达到一定的平衡,那就太好了。 K 通常是 5 或 10。

一个例子:

姓名1,日期1_1,位置1_1,号码1_1

名称1,日期1_2,位置1_2,编号1_2 ...

姓名1,日期1_5,位置1_5,号码1_5

name2、date2_1、location2_1、number2_1 ...

name2、date2_5、location2_5、number2_5 ...

name400、date400_1、location400_1、number400_1 ...

name400、date400_5、location400_5、number400_5

输出示例:

i,name1, date1_1, location1_1, number1_1

i,name1, date1_2, location1_2, number1_2 ...

i,name1, date1_5, location1_5, number1_5

j,name2, date2_1, location2_1, number2_1 ...

j,name2, date2_5, location2_5, number2_5 ...

k,name400, date400_1, location400_1, number400_1 ...

k,name400, date400_5, location400_5, number400_5

其中 1

【问题讨论】:

  • 那你有400个名字吗?
  • 问题很不清楚。预期的结果是什么,数据是什么样的,为什么您不能将它干净地划分为 1-20、21-40 广告。纳苏厄姆?也请提供示例
  • 是否可以将某个值 K 设置为 0,将第一组名称添加到 K=0,然后将 K 迭代为 1 .....直到 K = 5/10 然后循环回到K=0?我假设这是针对您提到的交叉验证的某些 ML 项目,所以您需要设计某种形式的随机抽样吗?
  • 我加了一个例子,谢谢你的建议。是的,分区是一种选择,但我不想假设数据集已经排序。

标签: python hash


【解决方案1】:

你想要的是一个哈希表,是吗?在这种情况下,只需创建一个大小为 K 的字典,并设计一个哈希函数,将您的字符串作为输入并返回索引。在您提供的示例中,合适的示例可能是:

h = int(name.split(',')[0].strip("name")) % K

公平地说,这是非常幼稚的,并且没有考虑到您的姓名分布(例如,name1 可能有很多,name400 可能很少)但如果他们更多或-不太一样,那么该方法应该可以很好地工作。

如果您的姓名没有那么方便,您可以创建一个辅助表,该表只需输入您的姓名并输出一个数字。例如,假设您有以下名字:“Bob”、“Sally”、“Larry”、...

nameIndexMappings = {"Bob" : 0, "Sally" : 1, "Larry" : 2}
h = nameIndexMappings[name.split(',')[0]] % K

然后你可以像这样设置另一个字典:

rowMapping = dict()
index = 0
for i in range(0, K):
    rowMapping[i] = list()
for row in rows:
    name = row.split(',')[0]
    if (name not in nameIndexMappings):
        nameIndexMappings[index] = name
        index += 1
    h = nameIndexMappings[name] % K
    rowMapping[h].append(row)

完成此操作后,rowMapping 应该包含 K 个列表,每个列表中的元素数量大致相同(当然,假设您的所有名称或多或少均等分布)。

【讨论】:

  • “name1”只是一个例子,我的名字中没有你想象的数字。名称可以是“麦当劳”、“星巴克”、“咖啡店”、“任何名称 123@”。所以我们可以假设名称分布良好,所以我担心的不是@bearrito 提到的情况,其中一个案例/名称非常占主导地位(但我同意这是一个普遍的观点)。
  • @hebeha 我想可能是这样。查看我的更新答案
  • 如果你的名字分布均匀,你能不能把哈希计算为哈希码模K?
  • 如果您愿意,也可以。我认为结果会相似
【解决方案2】:

如果没有更多限制,您的要求是不可行的。

想象一下,如果您的输入由输入字符串“A”N 次组成,其中 N 任意大,而输入字符串“B”仅 1 次。希望输出是什么?

无论如何你要做的就是解决装箱优化问题。

【讨论】:

    猜你喜欢
    • 2020-05-17
    • 2019-06-16
    • 2013-09-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多