Python 如何在代码中使求和更加动态

Python 如何在代码中使求和更加动态,python,Python,这是我的代码,它使用文本文件进行一些计算。我想让我的代码更动态,而不是像现在这样静态,我需要一些帮助,帮助我如何缩短代码,更具体地说,就是我计算总和的部分。我对python有点陌生,所以请容忍我 import numpy as np import math # Getting all the values in the file accept the first line file = open("history.txt", "r") next(file

这是我的代码,它使用文本文件进行一些计算。我想让我的代码更动态,而不是像现在这样静态,我需要一些帮助,帮助我如何缩短代码,更具体地说,就是我计算总和的部分。我对python有点陌生,所以请容忍我

import numpy as np
import math

# Getting all the values in the file accept the first line
file = open("history.txt", "r")
next(file)
lines = np.array([list(map(int,line.split())) for line in file])
mylist=np.unique(lines,axis=0)
print(f"Positive entries: {len(mylist)}")
file.close()
# Getting the first line of the file
file = open("history.txt", "r")
first_line = [list(map(int,line.split())) for line in file]
No_items = first_line[0][1]
No_Customers = first_line[0][0]
file.close()
# Creating a zeros array
vectors = np.zeros((No_items,No_Customers))
rows = [i[1] - 1 for i in lines]
# print(rows)
columns = [x[0] - 1 for x in lines]
# print(columns)
vectors[rows, columns] = 1
print(vectors)

number_of_vectors = len(vectors) * (len(vectors) - 1)

def calc_angle(x, y):
    norm_x = np.linalg.norm(x)
    norm_y = np.linalg.norm(y)
    cos_theta = np.dot(x, y) / (norm_x * norm_y)
    theta = math.degrees(math.acos(cos_theta))
    return theta

sum = (calc_angle(vectors[0],vectors[1]) + calc_angle(vectors[0],vectors[2]) + calc_angle(vectors[0],vectors[3]) + calc_angle(vectors[0],vectors[4]) 
+ calc_angle(vectors[1],vectors[0]) + calc_angle(vectors[1],vectors[2]) + calc_angle(vectors[1],vectors[3]) + calc_angle(vectors[1],vectors[4]) 
+ calc_angle(vectors[2],vectors[0])  + calc_angle(vectors[2],vectors[1]) + calc_angle(vectors[2],vectors[3]) + calc_angle(vectors[2],vectors[4]) 
+ calc_angle(vectors[3],vectors[0])  + calc_angle(vectors[3],vectors[1]) + calc_angle(vectors[3],vectors[2]) + calc_angle(vectors[3],vectors[4])
+ calc_angle(vectors[4],vectors[0])  + calc_angle(vectors[4],vectors[1]) + calc_angle(vectors[4],vectors[2]) + calc_angle(vectors[4],vectors[3]))

print(sum/number_of_vectors)

使用嵌套循环在两个维度上迭代:

sum = 0
for i in range(5):
    for j in range(5):
        if i != j:
            sum += calc_angle(vectors[i],vectors[j])
您还可以将内置的
sum
函数与。在这种情况下,您可能希望为变量指定一个不同的名称,以便不影响函数

total = sum(calc_angle(vectors[i], vectors[j]) for i in range(5) for j in range(5) if i != j)

要计算总和,可以执行以下操作:

total = 0 #using sum is not recommended as it is an in-built variable
for i in range(5):
       for j in range(5):
           if i!= j:
               total += calc_angle(vectors[i],vectors[j])
def和角度(行、列):
总数=0
对于范围内的i(行):
对于范围内的j(列):
总计=总计+计算角(i,j)
返回总计/(行*列)

您可以将其作为函数。

为什么要使用for循环?通过这样做,您可以以矢量化的方式进行此操作-

total = sum(calc_angle(vectors[i], vectors[j]) for i in range(5) for j in range(5) if i != j)
矢量化为成对工作 这是一种完全矢量化的方法,不使用np。矢量化签名。这将接受一个包含行向量的矩阵,并在求和之前对其运行成对计算

def calc_angle(vectors):
    norm = np.linalg.norm(vectors, axis=-1)
    cos_theta = np.dot(vectors,vectors.T) / np.outer(norm,norm)
    theta = np.degrees(np.arccos(cos_theta))
    
    np.fill_diagonal(theta, 0)
    return theta

np.sum(calc_angle(vectors)) #Takes in one set of vectors
矢量化为适用于2个独立矢量 这需要2个独立的向量(或向量集)作为输入,而不是一个矩阵。如果不希望在相同的输入向量之间进行成对距离计算,则还可以使用两组不同的向量

def calc_angle(x, y):
    norm_x = np.linalg.norm(x, axis=-1)
    norm_y = np.linalg.norm(y, axis=-1)
    cos_theta = np.dot(x,y.T) / np.outer(norm_x,norm_y)
    theta = np.degrees(np.arccos(cos_theta))
    
    np.fill_diagonal(theta, 0)
    return theta

np.sum(calc_angle(vectors, vectors)) #Takes 2 sets of vectors (could be same)
使用np.vectorize 这不是很有效,但在您遇到无法矢量化的代码时会有所帮助

def calc_angle(x, y):
    norm_x = np.linalg.norm(x)
    norm_y = np.linalg.norm(y)
    cos_theta = np.dot(x,y) / (norm_x * norm_y)
    theta = np.degrees(np.arccos(cos_theta))
    return theta

calc_angle_vec = np.vectorize(calc_angle, signature='(k),(k)->()')

sums = calc_angle_vec(vectors[None,:,:], vectors[:,None,:])
np.fill_diagonal(sums, 0)
output = np.sum(sums)
广泛的想法-

  • 这些方法通过在最后一个轴上取范数来计算所有向量之间的成对计算角
  • 然后,分子中的矩阵点通过范数的外部标准化得到距离
  • 然后将距离传递给numpy函数,这些函数被矢量化并将它们转换为相应的度数
  • 接下来,用0填充对角线(因为它们是相同的向量)
  • 最后用一个
    np.sum
    减少矩阵
  • 注意:我已将数学函数更改为等效的NumPy函数,因为它们支持矢量化


  • 我想让我的代码更具动态性,而不是静态性
    -这意味着什么?当我计算总和时,你可以看到,
    向量的形状是什么?这些值是硬编码的,所以我想用一种更简单的方法来计算总和,而不是我必须硬编码所有值。非常感谢你,它正在工作。您还告诉我sum是一个内置函数,我应该使用不同的变量名。每天我都会学到一些新东西。你可以完全避免使用for循环,numpy的美妙之处在于能够对代码进行矢量化。好吧,这对我来说有点太复杂了,但它可以工作。非常感谢。更新我的答案第二种方法比其他答案中提到的任何其他方法都要快得多,因为它是矢量化的,一旦你分别编写和运行每一行,它就非常简单。将第二种方法移到顶部,因为它应该是通过numpy解决此问题的正确方法。希望有帮助。如果有任何问题,请告诉我。