将数据填充到矩阵时降低时间复杂度 python
Reduce the time complexity while populating data into a matrix python
我有一个 core_df 数据框。每行都必须与其他行进行比较,结果必须存储在矩阵中。条件是如果开始或结束节点不匹配,或者如果长度比小于 0.2,则必须填充 0 其他值(比如 100)。
问题是数据框可能很大。它可以产生数百万条记录。
我为节省内存所做的是:
- 初始化稀疏 dok 矩阵
- 仅在上诊断矩阵中填充值(因为它将是下诊断矩阵的镜像)
- 更改了矩阵的数据类型,使其消耗更少的字节。
欢迎任何其他改进内存分配的建议。
我已经尝试了下面的代码,虽然它正在返回结果,但它在大型数据集上花费了大量时间。有没有办法优化时间复杂度?
import pandas as pd
import scipy
from scipy.sparse import dok_matrix
core_df = pd.DataFrame({'sno':[1,2,3,4],'start':[1,3,5,5],'end':[5,14,17,27],'start_elements':[('A', 'B'),('X','Y'),('B', 'C'),('B', 'C')],'end_elements':[('L', 'M'),('S', 'T'),('N', 'P'),('N', 'P')]})
core_df_count=len(core_df)
Score_matrix = dok_matrix((core_df_count, core_df_count))
for i in range(0, core_df_count):
start1 = core_df.iloc[i, 1]
end1 = core_df.iloc[i, 2]
Start_elements1 = core_df.iloc[i, 3]
End_elements1 = core_df.iloc[i, 4]
for j in range(i + 1, core_df_count):
start2 = core_df.iloc[j, 1]
end2 = core_df.iloc[j, 2]
Start_elements2 = core_df.iloc[j, 3]
End_elements2 = core_df.iloc[j, 4]
if Start_elements1 != Start_elements2 or End_elements1 != End_elements2:
Score_matrix[i, j] = 0
else:
ratio = (end1 - start1) / (end2 - start2)
if ratio <0.2:
Score_matrix[i, j] = 0
else:
Score_matrix[i,j]=100
Score_matrix_2D = pd.DataFrame(Score_matrix.todense())
Score_matrix_2D
- 首先,我根据
start_elements
& end_elements
对 df 进行分组,然后仅搜索
- 在每组中,我计算长度并制作密集矩阵比较长度(比率)。
- 我搜索哪个 df indices ratio >= 0.2
- 我没有将 0 分配给稀疏矩阵,只在必要时分配 100。默认到处都是0
import numpy as np
import pandas as pd
from scipy.sparse import dok_matrix
core_df = pd.DataFrame({'sno': [1, 2, 3, 4], 'start': [1, 3, 5, 5], 'end': [5, 14, 17, 27],
'start_elements': [('A', 'B'), ('X', 'Y'), ('B', 'C'), ('B', 'C')],
'end_elements': [('L', 'M'), ('S', 'T'), ('N', 'P'), ('N', 'P')]})
core_df_count = len(core_df)
Score_matrix = dok_matrix((core_df_count, core_df_count))
core_df_values = core_df.values
for (start_elements, end_elements), group_df in core_df.groupby(['start_elements', 'end_elements']):
lengths = (group_df['end'] - group_df['start']).values
ratios = np.divide.outer(lengths, lengths)
# I guess we should not take into account diagonal, so adding this:
ratios[np.arange(len(ratios)), np.arange(len(ratios))] = 0
where_is_above_threshold = np.where(ratios >= 0.2)
row_indices = group_df.index[where_is_above_threshold[0]]
column_indices = group_df.index[where_is_above_threshold[1]]
Score_matrix[row_indices, column_indices] = 100
Score_matrix_2D = pd.DataFrame(Score_matrix.todense())
print(Score_matrix_2D)
0 1 2 3
0 0.0 0.0 0.0 0.0
1 0.0 0.0 0.0 0.0
2 0.0 0.0 0.0 100.0
3 0.0 0.0 100.0 0.0
我有一个 core_df 数据框。每行都必须与其他行进行比较,结果必须存储在矩阵中。条件是如果开始或结束节点不匹配,或者如果长度比小于 0.2,则必须填充 0 其他值(比如 100)。 问题是数据框可能很大。它可以产生数百万条记录。 我为节省内存所做的是:
- 初始化稀疏 dok 矩阵
- 仅在上诊断矩阵中填充值(因为它将是下诊断矩阵的镜像)
- 更改了矩阵的数据类型,使其消耗更少的字节。 欢迎任何其他改进内存分配的建议。
我已经尝试了下面的代码,虽然它正在返回结果,但它在大型数据集上花费了大量时间。有没有办法优化时间复杂度?
import pandas as pd
import scipy
from scipy.sparse import dok_matrix
core_df = pd.DataFrame({'sno':[1,2,3,4],'start':[1,3,5,5],'end':[5,14,17,27],'start_elements':[('A', 'B'),('X','Y'),('B', 'C'),('B', 'C')],'end_elements':[('L', 'M'),('S', 'T'),('N', 'P'),('N', 'P')]})
core_df_count=len(core_df)
Score_matrix = dok_matrix((core_df_count, core_df_count))
for i in range(0, core_df_count):
start1 = core_df.iloc[i, 1]
end1 = core_df.iloc[i, 2]
Start_elements1 = core_df.iloc[i, 3]
End_elements1 = core_df.iloc[i, 4]
for j in range(i + 1, core_df_count):
start2 = core_df.iloc[j, 1]
end2 = core_df.iloc[j, 2]
Start_elements2 = core_df.iloc[j, 3]
End_elements2 = core_df.iloc[j, 4]
if Start_elements1 != Start_elements2 or End_elements1 != End_elements2:
Score_matrix[i, j] = 0
else:
ratio = (end1 - start1) / (end2 - start2)
if ratio <0.2:
Score_matrix[i, j] = 0
else:
Score_matrix[i,j]=100
Score_matrix_2D = pd.DataFrame(Score_matrix.todense())
Score_matrix_2D
- 首先,我根据
start_elements
&end_elements
对 df 进行分组,然后仅搜索 - 在每组中,我计算长度并制作密集矩阵比较长度(比率)。
- 我搜索哪个 df indices ratio >= 0.2
- 我没有将 0 分配给稀疏矩阵,只在必要时分配 100。默认到处都是0
import numpy as np
import pandas as pd
from scipy.sparse import dok_matrix
core_df = pd.DataFrame({'sno': [1, 2, 3, 4], 'start': [1, 3, 5, 5], 'end': [5, 14, 17, 27],
'start_elements': [('A', 'B'), ('X', 'Y'), ('B', 'C'), ('B', 'C')],
'end_elements': [('L', 'M'), ('S', 'T'), ('N', 'P'), ('N', 'P')]})
core_df_count = len(core_df)
Score_matrix = dok_matrix((core_df_count, core_df_count))
core_df_values = core_df.values
for (start_elements, end_elements), group_df in core_df.groupby(['start_elements', 'end_elements']):
lengths = (group_df['end'] - group_df['start']).values
ratios = np.divide.outer(lengths, lengths)
# I guess we should not take into account diagonal, so adding this:
ratios[np.arange(len(ratios)), np.arange(len(ratios))] = 0
where_is_above_threshold = np.where(ratios >= 0.2)
row_indices = group_df.index[where_is_above_threshold[0]]
column_indices = group_df.index[where_is_above_threshold[1]]
Score_matrix[row_indices, column_indices] = 100
Score_matrix_2D = pd.DataFrame(Score_matrix.todense())
print(Score_matrix_2D)
0 1 2 3
0 0.0 0.0 0.0 0.0
1 0.0 0.0 0.0 0.0
2 0.0 0.0 0.0 100.0
3 0.0 0.0 100.0 0.0