【问题标题】:Convert small numbers to a scale from 0 to 10将小数字转换为从 0 到 10 的范围
【发布时间】:2020-07-04 00:20:34
【问题描述】:

我有一个 url 列表->小数字。数字代表每个网址的重要性

url, value
https://mywebsite.com/p/1, 0.00212
https://mywebsite.com/p/2, 0.00208
https://mywebsite.com/p/3, 0.00201
https://mywebsite.com/p/4, 0.00138
https://mywebsite.com/p/5, 0.00067
https://mywebsite.com/p/1, 0.00001
...

假设值的总和 = 1 我想在 0-10 的范围内表示这些数字,并保持数字之间的一种比率差异

url, value, scaled_value
https://mywebsite.com/p/1, 0.00212, 10
https://mywebsite.com/p/2, 0.00208, 9
https://mywebsite.com/p/3, 0.00201, 9
https://mywebsite.com/p/4, 0.00138, 6
https://mywebsite.com/p/5, 0.00067, 3
https://mywebsite.com/p/1, 0.00001, 1
...

类似的东西(我不知道这里的比率差异是否保持不变) 任何人都可以帮助数学? 谢谢

#更新

感谢@annZen 的帮助,我尝试了两种方法,但结果不同,我不知道为什么。如果有人可以帮忙?

这是我使用的两个公式:

res1 = round(x*9/maxpri)+1
res2 = round(((x-minpri)/(maxpri-minpri))*10, 2)

【问题讨论】:

  • 你说的范围是 0 到 10,但是你的两个 res1 公式给出的值是 1 到 10。
  • 感谢@alaniwi,您认为仅此一项就可以解释数字的巨大差异吗?我的意思是顺序仍然相同,但值不同

标签: python math scale


【解决方案1】:

这是一种方法:

with open('file.txt', 'r') as p:
    lst = p.read().splitlines() # List all the lines of the file

lst2 = [float(i.split(', ')[1]) for i in lst[1:]] # List all the floats

num = [round(a*9/max(lst2))+1 for a in lst2] # List all the scaled numbers

for i,(l,n) in enumerate(zip(lst,['scaled_value']+num)):
    lst[i] = f"{l}, {n}" # Add the 'scaled_value' column

with open('file.txt', 'w') as p:
    p.write('\n'.join(lst)) # Write the updated data into the file

之前:

url, value
https://mywebsite.com/p/1, 0.00212
https://mywebsite.com/p/2, 0.00208
https://mywebsite.com/p/3, 0.00201
https://mywebsite.com/p/4, 0.00138
https://mywebsite.com/p/5, 0.00067
https://mywebsite.com/p/1, 0.00001

之后:

url, value, scaled_value
https://mywebsite.com/p/1, 0.00212, 10
https://mywebsite.com/p/2, 0.00208, 10
https://mywebsite.com/p/3, 0.00201, 10
https://mywebsite.com/p/4, 0.00138, 7
https://mywebsite.com/p/5, 0.00067, 4
https://mywebsite.com/p/1, 0.00001, 1



更新:

我的代码中进行转换的部分是:

num = [round(a*9/max(lst2))+1 for a in lst2]

其中lst2 只是从文件中提取的浮点数列表。您为我更新了问题以解释两者之间的区别

res1 = round(x*9/maxpri)+1
res2 = round(((x-minpri)/(maxpri-minpri))*10, 2)

让我们先看看我的列表理解:

num1 = [round(x*9/max(lst2))+1 for x in lst2]
num2 = [round(((x-min(lst2))/(max(lst2)-min(lst2)))*10, 2) for x in lst2]
print(num1)
print(num2)

输出:

[10, 10, 10, 7, 4, 1]
[10.0, 9.81, 9.48, 6.49, 3.13, 0.0]

第一个最明显的区别是我将答案四舍五入到最接近的整数。没有它,它将是:

num1 = [round(x*9/max(lst2), 2)+1 for x in lst2]
num2 = [round(((x-min(lst2))/(max(lst2)-min(lst2)))*10, 2) for x in lst2]
print(num1)
print(num2)

输出:

[10.0, 9.83, 9.53, 6.86, 3.84, 1.04]
[10.0, 9.81, 9.48, 6.49, 3.13, 0.0]

这些值现在非常接近,但还有一件事。我的代码假定缩放值的最小值是1,因为我在您的帖子https://mywebsite.com/p/1, 0.00001, 1 中看到了。我现在意识到你说的是 0-10,而不是 1-10。所以另一个是将9(10-1=9)更改为10(10-0=10),并删除+1

round(x*9/max(lst2), 2)+1
round(x*10/max(lst2), 2)

num1 = [round(x*10/max(lst2), 2) for x in lst2]
num2 = [round(((x-min(lst2))/(max(lst2)-min(lst2)))*10, 2) for x in lst2]
print(num1)
print(num2)

输出:

[10.0, 9.81, 9.48, 6.51, 3.16, 0.05]
[10.0, 9.81, 9.48, 6.49, 3.13, 0.0]

还有一点不同,那是因为我假设您的列中的最小值是0,因为您没有显示整个数组。但在这种情况下,它是0.00001。所以,继续:

num = [round(((x-min(lst2))/(max(lst2)-min(lst2)))*10, 2) for x in lst2]

总结:我的代码假设您希望数字从 1 缩放到 10,而不是 0 到 10,并且我的代码假设您的数据的最小值为 0,但情况可能并非如此。

【讨论】:

  • 嘿@annZen 感谢您的回答,我尝试了这种方法,您对此有何看法? stats.stackexchange.com/questions/70801/…
  • @DanyM 其实我用的方法是一样的逻辑:)
  • 是的@annZen,但我没有得到相同的结果,我已经用我的结果更新了线程,请告诉我你的想法
  • 好的,请稍等。
  • 哦,抱歉,问题是关于我们在哪里可以找到你进一步讨论,别介意,我看到你有一个 facebook 组和一个 youtube 频道 :)
【解决方案2】:

如果您想在数字之间保持一定的比率差异,可以将最小的数字设置为1,然后将其他所有数字设置为num/smallest

这种方法的问题在于它不能保证每个 URL 都设置为来自0 - 10 的数字。在上面的例子中,它会将数字分别设置为212, 208, 201, 138, 67, and 1

如果你真的需要将每个的数字设置在某个指定范围之间,你首先将最小的URL设置为重要0,将最大的URL设置为重要10。然后,所有其他点将位于斜率为(max value - min value)/10 的线上。下图展示了这个概念:

在这张图中,点的 y 值代表它们的 URL 值,x 坐标代表点的重要性。

【讨论】:

  • 嘿@Telescope 感谢您的回答,我尝试了这种方法,您对此有何看法? stats.stackexchange.com/questions/70801/…
  • 该方法遵循与我的方法类似的逻辑。我认为它对您的目的非常有用。
【解决方案3】:

如果这是用于生产代码,那么我建议使用csv.DictReadercsv.DictWriter,以便您稍后返回时易于阅读的代码。例如:

from csv import DictReader, DictWriter

scaled_field_name = 'scaled_value'

with open('input.csv') as fin:
    csvin = DictReader(fin, skipinitialspace=True)
    rows = list(csvin)

values = [float(row['value']) for row in rows]
min_value = min(values)
max_value = max(values)
for row, value in zip(rows, values):
    scaled = 10 * (value - min_value) / (max_value - min_value)
    row[scaled_field_name] = str(round(scaled))

with open('output.csv', 'w') as fout:
    csvout = DictWriter(fout, csvin.fieldnames + [scaled_field_name])
    csvout.writerows(rows)

(注意:逗号后面不会写空格,但是对于CSV来说应该是正常的。)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-01-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-29
    • 1970-01-01
    • 2017-10-02
    • 1970-01-01
    相关资源
    最近更新 更多