dataframe üzerinde jaccard benzerliğini hesapla

Nov 05 2020

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

EdgarRamírezMondragón Nov 05 2020 at 14:02

Sorunun daha kolay, ağırlıksız versiyonunun üstesinden gelmek, aşağıdaki adımlarla yapılabilir:

  1. 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 0
    
  2. Jaccard mesafesini hesaplamak için bağlantılı sorunuzdaki örneği takip edinscipy

    from 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