Chuyển từ điển từ điển thành một mảng mờ hoặc scipy, như bạn đang gặp phải, không quá nhiều niềm vui. Nếu bạn biết all_features
và all_labels
trước khi bàn tay, bạn có lẽ nên sử dụng ma trận COO thưa thớt scipy ngay từ đầu để giữ số lượng của bạn.
Cho dù điều đó là có thể hay không, bạn sẽ muốn giữ danh sách các tính năng và nhãn theo thứ tự sắp xếp, để tăng tốc độ tra cứu. Vì vậy, tôi sẽ cho rằng những điều sau đây không làm thay đổi một trong hai mảng:
all_features = np.array(all_features)
all_labels = np.array(all_labels)
all_features.sort()
all_labels.sort()
Cho phép trích xuất các nhãn trong data
theo thứ tự chúng được lưu trữ trong từ điển, và nhìn thấy nơi ở all_labels
không từng hạng mục sụp đổ:
labels = np.fromiter(data.iterkeys(), all_labels.dtype, len(data))
label_idx = np.searchsorted(all_labels, labels)
Bây giờ cho phép đếm có bao nhiêu tính năng nào mỗi nhãn có, và tính toán từ nó số lượng các mục khác không sẽ có trong mảng thưa thớt của bạn:
label_features = np.fromiter((len(c) for c in data.iteritems()), np.intp,
len(data))
indptr = np.concatenate(([0], np.cumsum(label_features)))
nnz = indptr[-1]
Bây giờ, chúng tôi trích xuất các tính năng cho mỗi nhãn, và số lượng tương ứng của họ
import itertools
features_it = itertools.chain(*(c.iterkeys() for c in data.itervalues()))
features = np.fromiter(features_it, all_features.dtype, nnz)
feature_idx = np.searchsorted(all_features, features)
counts_it = itertools.chain(*(c.itervalues() for c in data.itervalues()))
counts = np.fromiter(counts_it, np.intp, nnz)
Với những gì chúng ta có, chúng ta có thể tạo ra một ma trận CSR trực tiếp, với các nhãn như hàng và các tính năng như cột:
sps_data = csr_matrix((counts, feature_idx, indptr),
shape=(len(all_labels), len(all_features)))
Vấn đề duy nhất là các hàng của mảng thưa thớt này không theo thứ tự all_labels
, nhưng theo thứ tự chúng xuất hiện khi lặp qua data
.Nhưng chúng ta phải feature_idx
nói với chúng ta đâu mỗi nhãn kết thúc, và chúng ta có thể sắp xếp lại các hàng bằng cách thực hiện:
sps_data = sps_data[np.argsort(label_idx)]
Vâng, đó là lộn xộn, khó hiểu, và có lẽ không phải là rất nhanh, nhưng nó hoạt động, và nó sẽ có bộ nhớ hiệu quả hơn những gì bạn đề xuất trong câu hỏi của bạn:
>>> sps_data.A
array([[ 1, 45, 0],
[ 0, 1, 212]], dtype=int64)
>>> all_labels
array(['x', 'y'],
dtype='<S1')
>>> all_features
array(['a', 'b', 'c'],
dtype='<S1')
Tôi không biết cách tạo danh sách có thể nhanh hơn nhiều nếu bạn sử dụng python tinh khiết, vì tra cứu từ điển đã là thời gian cố định. Bạn đã thử sử dụng gõ tĩnh của các phần tử (ví dụ. Cython?) Bằng cách đó, bạn có thể tránh kiểm tra kiểu trên các phần tử danh sách khi bạn khởi tạo mảng numpy (nhưng tôi không chắc chắn nếu đó là nút cổ chai trong lần đầu tiên place) – Moritz
Tôi không biết đủ về 'numpy' /' scipy' để bình luận về cách "đúng cách" hóa hoạt động của bạn, nhưng bạn đang thực hiện một danh sách 500 * tỷ * yếu tố trước khi đưa nó trở nên uể oải. Xem nếu cho ăn 'np.fromiter' một biểu thức máy phát nhanh hơn cho bạn. – roippi
Có giải pháp nhanh hơn 100ms bằng cách sử dụng 'operator.itemgetter', nhưng tôi không nghĩ rằng sẽ đủ cho tập dữ liệu rất lớn. https: // db.tt/jMDAxs7i –