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


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.