dataframe üzerinde jaccard benzerliğini hesapla
Python'da kendi kendine öğrenen kişi, geliştirmeye çalışıyorum, bu yüzden her türlü yardıma açığız, çok teşekkürler! Veri çerçevemin bir sütunu üzerinde başka bir sütundaki ölçütleri eşleştirerek bir jakar benzerliği hesaplamak istiyorum. df şuna benzer:
name bag number item quantity
sally 1 BANANA 3
sally 2 BREAD 1
franck 3 BANANA 2
franck 3 ORANGE 1
franck 3 BREAD 4
robert 4 ORANGE 3
jenny 5 BANANA 4
jenny 5 ORANGE 2
Yaklaşık 80 kategorik ürünle, çanta numarası (numune) bir müşteriye özgüdür, ancak birden fazla olabilir ve miktarları 0 ile 4 arasında değişebilir. İçerikleri bir jakart benzerliği ile karşılaştırmak için çanta numaralarını yinelemek istiyorum her çift çantanın mesafesi. Mümkünse miktarı bir karşılaştırma ağırlığı olarak alma seçeneği ile. ideal sonuç, jakar benzerliğini kullanan Python Pandas Distance matrix gibi bir veri çerçevesi olacaktır.
Çözümün bunun arasında bir şey olduğunu hissediyorum> Bir pandas veri çerçevesinden jak kart benzerliği nasıl hesaplanır ve bir dask veri çerçevesindeki gruplara özel bir işlev nasıl uygulanır, işlev girdisi olarak birden çok sütun kullanılarak
İki değişkenli jak kartı işlevini ayarlamak için bir maskeyi yinelemem gerektiğini düşünüyorum. Ancak gördüğüm her örnekte, karşılaştırılacak öğeler farklı sütunlardadır. Bu yüzden biraz kayboldum, burada ... yardım ettiğin için çok teşekkürler! şerefe
Yanıtlar
Sorunun daha kolay, ağırlıksız versiyonunun üstesinden gelmek, aşağıdaki adımlarla yapılabilir:
mevcut veri çerçevenizle bir pivot tablo oluşturun
p = df.pivot_table( index='bag_number', columns='item', values='quantity', ).fillna(0) # Convert NaN to 0Jaccard mesafesini hesaplamak için bağlantılı sorunuzdaki örneği takip edin
scipyfrom scipy.spatial.distance import jaccard, pdist, squareform m = 1 - squareform(pdist(p.astype(bool), jaccard)) sim = pd.DataFrame(m, index=p.index, columns=p.index)
Sonuç:
bag_number 1 2 3 4 5
bag_number
1 1.000000 0.000000 0.333333 0.000000 0.500000
2 0.000000 1.000000 0.333333 0.000000 0.000000
3 0.333333 0.333333 1.000000 0.333333 0.666667
4 0.000000 0.000000 0.333333 1.000000 0.500000
5 0.500000 0.000000 0.666667 0.500000 1.000000
Ağırlıklı versiyon sadece biraz daha karmaşıktır. pdistFonksiyon sadece özel bir benzerlik (veya mesafe) işlevini oluşturmanız gerekir bu yüzden, bütün karşılaştırmalar için geçerli olacağını bir vektör desteklemektedir. Wikipedia'ya göre ağırlıklı versiyon şu şekilde hesaplanabilir:
import numpy as np
def weighted_jaccard_distance(x, y):
arr = np.array([x, y])
return 1 - arr.min(axis=0).sum() / arr.max(axis=0).sum()
Artık ağırlıklı benzerliği hesaplayabilirsiniz
sim_weighted = pd.DataFrame(
data=1 - squareform(pdist(p, weighted_jaccard_distance)),
index=p.index,
columns=p.index,
)
Sonuç:
bag_number 1 2 3 4 5
bag_number
1 1.00 0.000000 0.250000 0.000000 0.500000
2 0.00 1.000000 0.142857 0.000000 0.000000
3 0.25 0.142857 1.000000 0.111111 0.300000
4 0.00 0.000000 0.111111 1.000000 0.285714
5 0.50 0.000000 0.300000 0.285714 1.000000