Python 将小数字转换为从0到10的刻度

Python 将小数字转换为从0到10的刻度,python,math,scale,Python,Math,Scale,我有一个URL列表->小数字。数字代表每个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

我有一个URL列表->小数字。数字代表每个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
...
类似这样的情况(我不知道这里的比率差是否保持在tho) 有人能帮我学数学吗? 谢谢

#更新

多亏@annZen的帮助,我尝试了两种方法,但结果不同,我不知道为什么。如果有人能帮忙

以下是我使用的两个公式:

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

如果您想保持两个数字之间一定的比率差,可以将最小的数字设置为
1
,然后每隔一个数字设置为
num/minimate

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

如果确实需要将每个数字设置为介于特定范围之间,则首先将最小URL设置为重要性
0
,将最大URL设置为重要性
10
。然后,所有其他点将位于坡度
(最大值-最小值)/10
的线上。下图展示了这一概念:

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

这里有一种方法:

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]
[10.0, 9.83, 9.53, 6.86, 3.84, 1.04]
[10.0, 9.81, 9.48, 6.49, 3.13, 0.0]
[10.0, 9.81, 9.48, 6.51, 3.16, 0.05]
[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, 10, 10, 7, 4, 1]
[10.0, 9.81, 9.48, 6.49, 3.13, 0.0]
[10.0, 9.83, 9.53, 6.86, 3.84, 1.04]
[10.0, 9.81, 9.48, 6.49, 3.13, 0.0]
[10.0, 9.81, 9.48, 6.51, 3.16, 0.05]
[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)

输出:

[10, 10, 10, 7, 4, 1]
[10.0, 9.81, 9.48, 6.49, 3.13, 0.0]
[10.0, 9.83, 9.53, 6.86, 3.84, 1.04]
[10.0, 9.81, 9.48, 6.49, 3.13, 0.0]
[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,情况可能并非如此。如果这是针对生产代码,然后,我建议使用
csv.DictReader
csv.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来说应该是正常的。)

hey@Telescope谢谢你的回答,我尝试了这种方法,你怎么看?这种方法遵循与我的方法相似的逻辑。我认为这对你的目的来说非常有效。嘿@annZen谢谢你的回答,我试过这种方法,你怎么看@DanyM事实上,我使用的方法是相同的逻辑:)是@annZen,但我没有得到相同的结果,我用我的结果更新了线程,请告诉我你的想法当然,给我一分钟。哦,对不起,问题是关于在哪里可以找到你进一步讨论,不介意,我看到你有一个facebook群组和一个youtube频道:)你说的是0到10的范围,但是你的两个
res1
公式给出的值是1到10。谢谢@alaniwi你认为单凭这一点就可以解释数字之间的巨大差异吗?我的意思是顺序仍然相同,但数值不同