जाँच करें कि क्या पंडों के कॉलम में किसी सूची से सभी तत्व हैं


20

मेरे पास इस तरह एक df है:

frame = pd.DataFrame({'a' : ['a,b,c', 'a,c,f', 'b,d,f','a,z,c']})

और मदों की एक सूची:

letters = ['a','c']

मेरा लक्ष्य सभी पंक्तियों को प्राप्त करना frameहै जिसमें कम से कम 2 तत्व शामिल हैंletters

मैं इस समाधान के साथ आया:

for i in letters:
    subframe = frame[frame['a'].str.contains(i)]

यह मुझे वही देता है जो मैं चाहता हूं, लेकिन यह स्केलेबिलिटी के मामले में सबसे अच्छा समाधान नहीं हो सकता है। क्या कोई 'सदिश' समाधान है? धन्यवाद


4
यह आपको केवल पंक्तियाँ देगा जिनमें अंतिम अक्षर होता है क्योंकि आप किसी भी पुनरावृत्ति में सबफ़्रेम ओवरराइड करते हैं
— टॉम रॉन

@TomRon आप सही कह रहे हैं, क्या
— मंद है

जवाबों:


12

मैं श्रृंखला की एक सूची बनाऊंगा, और फिर एक वेक्टर लागू करूंगा np.all:

contains = [frame['a'].str.contains(i) for i in letters]
resul = frame[np.all(contains, axis=0)]

यह उम्मीद के अनुसार देता है:

       a
0  a,b,c
1  a,c,f
3  a,z,c

3
100k पर बधाई!
— पीटर हदद

14

एक तरीका यह है कि स्तंभ मानों को उपयोग की गई सूचियों में विभाजित किया जाए str.split, और जाँचें कि set(letters)क्या subsetप्राप्त सूचियों में से एक है:

letters_s = set(letters)
frame[frame.a.str.split(',').map(letters_s.issubset)]

     a
0  a,b,c
1  a,c,f
3  a,z,c
​

बेंचमार्क:

def serge(frame):
    contains = [frame['a'].str.contains(i) for i in letters]
    return frame[np.all(contains, axis=0)]

def yatu(frame):
    letters_s = set(letters)
    return frame[frame.a.str.split(',').map(letters_s.issubset)]

def austin(frame):
    mask =  frame.a.apply(lambda x: np.intersect1d(x.split(','), letters).size > 0)
    return frame[mask]

def datanovice(frame):
    s = frame['a'].str.split(',').explode().isin(letters).groupby(level=0).cumsum()
    return frame.loc[s[s.ge(2)].index.unique()]

perfplot.show(
    setup=lambda n: pd.concat([frame]*n, axis=0).reset_index(drop=True), 

    kernels=[
        lambda df: serge(df),
        lambda df: yatu(df),
        lambda df: df[df['a'].apply(lambda x: np.all([*map(lambda l: l in x, letters)]))],
        lambda df: austin(df),
        lambda df: datanovice(df),
    ],

    labels=['serge', 'yatu', 'bruno','austin', 'datanovice'],
    n_range=[2**k for k in range(0, 18)],
    equality_check=lambda x, y: x.equals(y),
    xlabel='N'
)

यहाँ छवि विवरण दर्ज करें


TypeError: unhashable type: 'set'जब मैं आपका कोड चलाऊंगा तो मुझे मिलेगा ? इसे प्रदान किए गए फ्रेम
— अबो

क्या संस्करण? @Datanovice डबल चेकिंग और सब ठीक लगता है
— yatu

मेरा पांडा है 1.0.3और अजगर 3.7शायद सिर्फ मुझे है
— डेटानोविस

3
@Datanovice मुझे लगता है कि आपको इसके लिए अजगर 3.8 की आवश्यकता है :)
— aky

2
धन्यवाद, मुझे @Datanovice के रूप में एक ही त्रुटि मिलती है और यह अजगर के लिए कूद नहीं सकता है 3.8 दुर्भाग्य से
— Kauber

7

आप उपयोग कर सकते हैं np.intersect1d:

import pandas as pd
import numpy as np

frame = pd.DataFrame({'a' : ['a,b,c', 'a,c,f', 'b,d,f','a,z,c']})
letters = ['a','c']

mask =  frame.a.apply(lambda x: np.intersect1d(x.split(','), letters).size > 0)
print(frame[mask])

    a
0  a,b,c
1  a,c,f
3  a,z,c


6

उपयोग set.issubset :

frame = pd.DataFrame({'a' : ['a,b,c', 'a,c,f', 'b,d,f','a,z,c','x,y']})
letters = ['a','c']

frame[frame['a'].apply(lambda x: set(letters).issubset(x))]

Out:

       a
0  a,b,c
1  a,c,f
3  a,z,c

5

IIUC, explodeऔर बूलियन फ़िल्टर

एक श्रृंखला बनाने के लिए विचार है तो हम एक संचयी राशि का उपयोग करके अपनी सूची की वास्तविक घटनाओं की गणना कर सकते हैं

s = frame['a'].str.split(',').explode().isin(letters).groupby(level=0).cumsum()

print(s)

0    1.0
0    1.0
0    2.0
1    1.0
1    2.0
1    2.0
2    0.0
2    0.0
2    0.0
3    1.0
3    1.0
3    2.0

frame.loc[s[s.ge(2)].index.unique()]

out:

       a
0  a,b,c
1  a,c,f
3  a,z,c

1
frame.iloc[[x for x in range(len(frame)) if set(letters).issubset(frame.iloc[x,0])]]

उत्पादन:

        a
 0  a,b,c
 1  a,c,f
 3  a,z,c

timeit

%%timeit
#hermes
frame.iloc[[x for x in range(len(frame)) if set(letters).issubset(frame.iloc[x,0])]]

उत्पादन

300 µs ± 32.9 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.