सुमी में जल्दी से सममित जोड़े खोजें


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]

मैं इस डेटा फ़्रेम में सभी सममित जोड़े के अंतिम डुप्लिकेट को कैसे ढूंढूं, पहचानूं, और कैसे निकालूं?

सममितीय जोड़ी का एक उदाहरण है कि '(0, 1)' '(1, 0)' के बराबर है। बाद को हटा दिया जाना चाहिए।

एल्गोरिथ्म तेज़ होना चाहिए, इसलिए इसे सुन्न करने की सलाह दी जाती है। अजगर वस्तु में परिवर्तित होने की अनुमति नहीं है।


1
क्या आप इस बात का उदाहरण दे सकते हैं कि आप क्या समझते हैं symmetric pairs?
यतु

(0, 1) == (1,0) सच है
द अनफिन कैट

1
क्या (0, 1) == (0, 1) भी सही है?
wundermahn

@JerryM। हां, लेकिन इसे हटाने के लिए तुच्छ हैdf.drop_duplicates()
अनफिन कैट

2
@ molybdenum42 मैं एक उदाहरण बनाने के लिए itertools उत्पाद का उपयोग करता हूं, डेटा स्वयं itertools उत्पाद के साथ निर्मित नहीं हैं।
अनफिन कैट

जवाबों:


13

आप मानों को क्रमबद्ध कर सकते हैं, फिर groupby:

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

विकल्प 2 : यदि आपके पास बहुत सारे जोड़े हैं c1, c2, तो groupbyयह धीमा हो सकता है। उस स्थिति में, हम नए मान निर्दिष्ट कर सकते हैं और फ़िल्टर कर सकते हैं 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

एक तरह से उपयोग कर रहा है np.uniqueके साथ return_index=Trueऔर सूचकांक dataframe के परिणाम का उपयोग करें:

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
हाँ अन्यथा अद्वितीय सममित जोड़े @DanielMesejo का पता लगाने में विफल रहता है
yatu

ठीक है, मैं देख रहा हूं कि आप जोड़े को
छांट

हां, लेकिन मेरा मतलब है कि आप [1, 0] को [0, 1] में बदल देंगे?
दानी मेज़ो

6

frozenset

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

df[~mask]

1
क्या आप यहां प्रत्येक स्तंभ पर टुपल्स पर धीरे-धीरे चलना नहीं चाहते हैं? फिर भी, upvote।
अनफिन कैट

हाँ, मैं पुनरावृत्ति कर रहा हूँ। नहीं, यह उतना धीमा नहीं है जितना आप सोचते हैं।
piRSquared

5

मैं करूँगा

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

पांडा और सुन्न त्रिक से

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

यहाँ पूर्णांक के लिए एक NumPy आधारित है -

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

यदि आप इंडेक्स डेटा को रखना चाहते हैं, तो इसका उपयोग करें return df.iloc[np.sort(sidx[m])]

जेनेरिक नंबरों (ints / फ़्लोट्स इत्यादि) के लिए, हम एक का उपयोग करेंगे view-based-

# 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()

और केवल प्राप्त करने के लिए कदम की जगह idxके साथ idx = view1D(b)में remove_symm_pairs


1

यदि इसे तेज करने की आवश्यकता है , और यदि आपके चर पूर्णांक हैं, तो निम्नलिखित चाल मदद कर सकती है: v,wअपने वेक्टर के कॉलम होने दें ; निर्माण [v+w, np.abs(v-w)] =: [x, y]; फिर इस मैट्रिक्स को लेक्सोग्राफिक रूप से क्रमबद्ध करें, डुप्लिकेट निकालें, और अंत में इसे वापस मैप करें [v, w] = [(x+y), (x-y)]/2

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.