Hızlıca simetrik çiftleri bulun


15
from itertools import product
import pandas as pd

df = pd.DataFrame.from_records(product(range(10), range(10)))
df = df.sample(90)
df.columns = "c1 c2".split()
df = df.sort_values(df.columns.tolist()).reset_index(drop=True)
#     c1  c2
# 0    0   0
# 1    0   1
# 2    0   2
# 3    0   3
# 4    0   4
# ..  ..  ..
# 85   9   4
# 86   9   5
# 87   9   7
# 88   9   8
# 89   9   9
# 
# [90 rows x 2 columns]

Bu veri çerçevesindeki tüm simetrik çiftlerin son kopyasını hızlı bir şekilde nasıl bulabilirim, belirleyebilir ve kaldırabilirim?

Simetrik çiftin bir örneği '(0, 1)' ifadesinin '(1, 0)' değerine eşit olmasıdır. İkincisi çıkarılmalıdır.

Algoritma hızlı olmalıdır, bu nedenle numpy kullanılması önerilir. Python nesnesine dönüştürmeye izin verilmiyor.


1
Neyi anladığınıza bir örnek verebilir misiniz symmetric pairs?
yatu

(0, 1) == (1,0) Doğru
Unfun Cat

1
(0, 1) == (0, 1) de Doğru mu?
wundermahn

@JerryM. Evet, ancak kaldırmak önemsizdf.drop_duplicates()
The Unfun Cat

2
@ molybdenum42 Bir örnek oluşturmak için itertools ürününü kullanıyorum, verilerin kendileri itertools ürünü ile oluşturulmuyor.
Unfun Cat

Yanıtlar:


13

Değerleri sıralayabilir, ardından groupby:

a= np.sort(df.to_numpy(), axis=1)
df.groupby([a[:,0], a[:,1]], as_index=False, sort=False).first()

Seçenek 2 : Çok fazla çiftiniz varsa c1, c2, groupbyyavaş olabilir. Bu durumda, yeni değerler atayabilir ve şunlara göre filtreleyebiliriz drop_duplicates:

a= np.sort(df.to_numpy(), axis=1) 

(df.assign(one=a[:,0], two=a[:,1])   # one and two can be changed
   .drop_duplicates(['one','two'])   # taken from above
   .reindex(df.columns, axis=1)
)

7

Tek yönlü kullanıyor np.uniqueile return_index=Trueve endeks dataframe sonucu kullanın:

a = np.sort(df.values)
_, ix = np.unique(a, return_index=True, axis=0)

print(df.iloc[ix, :])

    c1  c2
0    0   0
1    0   1
20   2   0
3    0   3
40   4   0
50   5   0
6    0   6
70   7   0
8    0   8
9    0   9
11   1   1
21   2   1
13   1   3
41   4   1
51   5   1
16   1   6
71   7   1
...

1
Evet aksi takdirde benzersiz simetrik çiftleri tespit edemez @DanielMesejo
yatu

Tamam, görüyorum ki çiftleri
sıralıyorsun

Evet ama demek istediğim [1, 0] 'ı [0, 1]' e dönüştürdün değil mi?
Dani Mesejo

6

frozenset

mask = pd.Series(map(frozenset, zip(df.c1, df.c2))).duplicated()

df[~mask]

1
Buradaki her sütunun üzerinde tupllar üzerinde yavaşça tekrar ediyor musunuz? Yine de oy verin.
Unfun Cat

Evet, tekrar ediyorum. Hayır, düşündüğünüz kadar yavaş değil.
piRSquared

5

yapacağım

df[~pd.DataFrame(np.sort(df.values,1)).duplicated().values]

Pandalardan ve numpy tri'den

s=pd.crosstab(df.c1,df.c2)
s=s.mask(np.triu(np.ones(s.shape)).astype(np.bool) & s==0).stack().reset_index()

5

İşte tamsayılar için bir NumPy tabanlı -

def remove_symm_pairs(df):
    a = df.to_numpy(copy=False)
    b = np.sort(a,axis=1)
    idx = np.ravel_multi_index(b.T,(b.max(0)+1))
    sidx = idx.argsort(kind='mergesort')
    p = idx[sidx]
    m = np.r_[True,p[:-1]!=p[1:]]
    a_out = a[np.sort(sidx[m])]
    df_out = pd.DataFrame(a_out)
    return df_out

Dizin verilerini olduğu gibi tutmak istiyorsanız, kullanın return df.iloc[np.sort(sidx[m])].

Jenerik sayılar (ints / yüzen, vb) için, bir kullanacak view-basedbirini -

# https://stackoverflow.com/a/44999009/ @Divakar
def view1D(a): # a is array
    a = np.ascontiguousarray(a)
    void_dt = np.dtype((np.void, a.dtype.itemsize * a.shape[1]))
    return a.view(void_dt).ravel()

ve basitçe almak için adım değiştirmek idxile idx = view1D(b)de remove_symm_pairs.


1

Bunun hızlı olması gerekiyorsa ve değişkenleriniz tamsayı ise, aşağıdaki hile yardımcı olabilir: Bırakın v,wvektörünüzün sütunları olsun ; yapı [v+w, np.abs(v-w)] =: [x, y]; daha sonra bu matrisi sözlükbilimsel olarak sıralayın, kopyaları kaldırın ve son olarak tekrar eşleyin [v, w] = [(x+y), (x-y)]/2.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.