基于阵列输入的矢量化算法

2024-04-23 07:56:19 发布

您现在位置:Python中文网/ 问答频道 /正文

我想从dataframe以向量化的方式创建一个备用矩阵,包含标签向量和值向量,同时知道所有标签。你知道吗

另一个限制是,我不能先创建密集数据帧,然后再将其转换为备用数据帧,因为它太大了,无法保存在内存中。你知道吗


示例:

所有可能的标签列表:

all_labels = ['a','b','c','d','e',\
          'f','g','h','i','j',\
          'k','l','m','n','o',\
          'p','q','r','s','t',\
          'u','v','w','z']

每行中具有特定标签值的数据帧:

data = {'labels': [['b','a'],['q'],['n','j','v']],
        'scores': [[0.1,0.2],[0.7],[0.3,0.5,0.1]]}
df = pd.DataFrame(data)

df

预期密集输出:

matrix


这是我如何以非矢量化的方式完成的,这占用了太多的时间:

from scipy import sparse
from scipy.sparse import coo_matrix

def labels_to_sparse(input_):
    all_, lables_, scores_ = input_
    rows = [0]*len(all_)
    cols = range(len(all_))
    vals = [0]*len(all_)
    for i in range(len(lables_)):
        vals[all_.index(lables_[i])] = scores_[i]

    return coo_matrix((vals, (rows, cols)))

df['sparse_row'] = df.apply(
        lambda x: labels_to_sparse((all_labels, x['labels'], x['scores'])), axis=1
)

df

尽管这是可行的,但由于必须使用df.apply,对于较大的数据来说速度非常慢。有没有办法将这个函数矢量化,以避免使用apply?你知道吗

最后,我想用这个数据帧来创建矩阵:

my_result = sparse.vstack(df['sparse_row'].values)
my_result.todense() #not really needed - just for visualization

编辑

总结可接受的解决方案(由@Divakar提供):

all_labels = np.sort(all_labels)


n = len(df)
lens = list(map(len,df['labels']))
l_ar = np.concatenate(df['labels'].to_list())
d = np.concatenate(df['scores'].to_list())
R = np.repeat(np.arange(n),lens)
C = np.searchsorted(all_labels,l_ar)

my_result = coo_matrix( (d, (R, C)), shape = (n,len(all_labels)))

Tags: to数据dflabelslennp标签all
2条回答

这是一个基于^{}-

n = len(df)
lens = list(map(len,df['labels']))
l_ar = np.concatenate(df['labels'])
d = np.concatenate(df['scores'])
out = np.zeros((n,len(all_labels)),dtype=d.dtype)
R = np.repeat(np.arange(n),lens)
C = np.searchsorted(all_labels,l_ar)
out[R, C] = d

注意:如果all_labels没有排序,我们需要将sorterarg与searchsorted一起使用。你知道吗

要获得稀疏矩阵输出,如^{}-

from scipy.sparse import csr_matrix,coo_matrix

out_sparse = coo_matrix( (d, (R, C)), shape = (n,len(all_labels)))

这里有几个你可以尝试的替代方法。你知道吗

方法1-用列表理解和^{}

重新构造你的DataFrame
from string import ascii_lowercase

all_labels = list(ascii_lowercase)

my_result = (pd.DataFrame([dict(zip(l, v)) for _, (l, v) in df.iterrows()])
             .reindex(columns=all_labels).fillna(0).values)

方法2-for loop,使用^{}

更新值
my_result = pd.DataFrame(np.zeros((len(df), len(all_labels))), columns=all_labels)

for i, (lab, val) in df.iterrows():
    my_result.loc[i, lab] = val

my_result = my_result.values

两者应产生相同的产出。你知道吗

[输出]

[[0.2 0.1 0.  0.  0.  0.  0.  0.  0.  0.  0.  0.  0.  0.  0.  0.  0.  0.
  0.  0.  0.  0.  0.  0.  0.  0. ]
 [0.  0.  0.  0.  0.  0.  0.  0.  0.  0.  0.  0.  0.  0.  0.  0.  0.7 0.
  0.  0.  0.  0.  0.  0.  0.  0. ]
 [0.  0.  0.  0.  0.  0.  0.  0.  0.  0.5 0.  0.  0.  0.3 0.  0.  0.  0.
  0.  0.  0.  0.1 0.  0.  0.  0. ]]

相关问题 更多 >