क्या पंडों को चलाने का एक सीधा तरीका है। DataFrame.isin समानांतर में?


25

मेरे पास एक मॉडलिंग और स्कोरिंग कार्यक्रम है जो DataFrame.isinकुछ हजार विशिष्ट पृष्ठों में से प्रत्येक के लिए अलग-अलग उपयोगकर्ताओं के रिकॉर्ड जैसे "फेसबुक" की सूची के माध्यम से पांडा के कार्य का भारी उपयोग करता है। यह कार्यक्रम का सबसे अधिक समय लेने वाला हिस्सा है, मॉडलिंग या स्कोरिंग टुकड़ों की तुलना में अधिक, बस इसलिए कि यह केवल एक कोर पर चलता है जबकि बाकी एक साथ कुछ दर्जन पर चलता है।

हालांकि मुझे पता है कि मैं मैन्युअल रूप से डेटाफ़्रेम को विखंडू में तोड़ सकता हूं और समानांतर में ऑपरेशन चला सकता हूं, क्या स्वचालित रूप से ऐसा करने का कोई सीधा तरीका है? दूसरे शब्दों में, क्या वहाँ किसी भी तरह का पैकेज है जो पहचान लेगा कि मैं आसानी से प्रत्यायोजित ऑपरेशन चला रहा हूँ और इसे स्वचालित रूप से वितरित कर रहा हूँ? शायद यह बहुत ज्यादा पूछ रहा है, लेकिन मैं पहले से ही हैरान हो गया हूं कि पहले से ही पाइथन में क्या उपलब्ध है, इसलिए मुझे यह पूछने लायक है।

यह कैसे पूरा किया जा सकता है इसके बारे में कोई अन्य सुझाव (भले ही कुछ जादू गेंडा पैकेज द्वारा नहीं!) भी सराहना की जाएगी। मुख्य रूप से, बस समाधान कोडिंग समय की एक समान राशि खर्च किए बिना 15-20 मिनट प्रति रन से दाढ़ी बनाने का एक तरीका खोजने की कोशिश कर रहा है।


आपके मूल्यों की सूची कितनी बड़ी है? क्या आपने इसे एक सेट के रूप में पारित करने की कोशिश की है? समानता के लिए, आपको जॉबलिब में दिलचस्पी हो सकती है। इसका उपयोग करना आसान है और कम्प्यूटेशन को गति दे सकता है। डेटा के बड़े हिस्से के साथ इसका उपयोग करें।
ओओ

एक अन्य विकल्प अपनी समस्या को एक जुड़ाव के रूप में फिर से लिखना है। पंडों stackoverflow.com/questions/23945493/…
ब्रायन स्पिरिंग

फिर भी एक अन्य विकल्प np.in1d ​​का उपयोग किया जाता है, जो तेजी से stackoverflow.com/questions/21738882/fast-pandas-filtering
ब्रायन

जवाबों:


8

दुर्भाग्य से, पांडा में अभी तक समानांतरकरण लागू नहीं किया गया है। यदि आप इस सुविधा के विकास में भाग लेना चाहते हैं तो आप इस github मुद्दे में शामिल हो सकते हैं।

मैं इस उद्देश्य के लिए कोई "जादू गेंडा पैकेज" नहीं जानता, इसलिए सबसे अच्छी बात यह है कि आप अपना समाधान लिखेंगे। लेकिन अगर आप अभी भी उस पर समय नहीं बिताना चाहते हैं और कुछ नया सीखना चाहते हैं - तो आप MongoDB (मैप कम और एग फ्रेमवर्क) में निर्मित दो तरीकों की कोशिश कर सकते हैं। Mongodb_agg_framework देखें ।


6

मुझे लगता है कि आपका सबसे अच्छा दांव रस्सेटा होगा । मुझे यह बेहद उपयोगी और आसान लग रहा है। इसकी पांडा विधि की जाँच करें ।

आप इसे पाइप द्वारा प्राप्त कर सकते हैं ।


मैं सीधे GitHub जाने से rosetta प्राप्त करने की सलाह दूंगा। यह सुनिश्चित करता है कि आप नवीनतम संस्करण प्राप्त करें। github.com/columbia-applied-data-science/rosetta
इयान लैंगमोर


0

इस सवाल का एक और अधिक सामान्य संस्करण है पंडों पर समानांतरकरण समारोह लागू करता है - तो यह एक ताज़ा प्रश्न है :)

सबसे पहले , मैं स्विफ्ट का उल्लेख करना चाहता हूं क्योंकि आपने "पैक किया हुआ" समाधान के लिए कहा था, और यह पांडा के समांतरीकरण के संबंध में सबसे अधिक एसओ प्रश्न पर दिखाई देता है।

लेकिन .. मैं अभी भी इसके लिए अपना व्यक्तिगत जिस्ट कोड साझा करना चाहूंगा, क्योंकि डेटाफ्रेम के साथ काम करने के कई वर्षों के बाद मुझे कभी भी 100% समांतरकरण समाधान (मुख्य रूप से लागू फ़ंक्शन के लिए) नहीं मिला और मुझे हमेशा अपने लिए वापस आना पड़ा " मैनुअल "कोड।

आपके लिए धन्यवाद, मैंने इसके नाम से किसी भी (सैद्धांतिक रूप से) डेटाफ़्रेम विधि का समर्थन करने के लिए इसे और अधिक सामान्य बना दिया है (इसलिए आपको आइसिन, आवेदन, आदि के लिए संस्करण रखने की आवश्यकता नहीं होगी)।

मैंने इसे "isin", "apply" और "isna" कार्यों पर अजगर 2.7 और 3.6 दोनों का उपयोग करके परीक्षण किया। यह 20 लाइनों के तहत है, और मैंने "सबसेट" और "नोजर" जैसे पांडा के नामकरण सम्मेलन का पालन किया।

मैंने "isin" के लिए dask समतुल्य कोड के साथ एक समय की तुलना भी जोड़ी है और यह ~ X2 बार धीमा होता है तो यह संकेत देता है।

इसमें 2 कार्य शामिल हैं:

df_multi_core - यह वह है जिसे आप कॉल करते हैं। यह स्वीकार करता है:

  1. आपकी df ऑब्जेक्ट
  2. वह फ़ंक्शन नाम जिसे आप कॉल करना चाहते हैं
  3. स्तंभों के सबसेट को फ़ंक्शन पर किया जा सकता है (समय / मेमोरी कम करने में मदद करता है)
  4. समानांतर में चलने वाली नौकरियों की संख्या (-1 या सभी कोर के लिए छोड़ दें)
  5. कोई भी अन्य df का फ़ंक्शन स्वीकार करता है (जैसे "अक्ष")

_df_split - यह एक आंतरिक सहायक फ़ंक्शन है जिसे विश्व स्तर पर चल रहे मॉड्यूल में रखा जाना है (Pool.map "प्लेसमेंट निर्भर" है), अन्यथा मैं इसे आंतरिक रूप से ढूँढूँगा।

यहाँ मेरे जीस्ट से एक कोड है (मैं वहां और पंडों के समारोह परीक्षण जोड़ूंगा):

import pandas as pd
import numpy as np
import multiprocessing
from functools import partial

def _df_split(tup_arg, **kwargs):
    split_ind, df_split, df_f_name = tup_arg
    return (split_ind, getattr(df_split, df_f_name)(**kwargs))

def df_multi_core(df, df_f_name, subset=None, njobs=-1, **kwargs):
    if njobs == -1:
        njobs = multiprocessing.cpu_count()
    pool = multiprocessing.Pool(processes=njobs)

    try:
        splits = np.array_split(df[subset], njobs)
    except ValueError:
        splits = np.array_split(df, njobs)

    pool_data = [(split_ind, df_split, df_f_name) for split_ind, df_split in enumerate(splits)]
    results = pool.map(partial(_df_split, **kwargs), pool_data)
    pool.close()
    pool.join()
    results = sorted(results, key=lambda x:x[0])
    results = pd.concat([split[1] for split in results])
    return results

Bellow एक समांतर आइसिन के लिए एक परीक्षण कोड है, जिसमें मूल, मल्टी-कोर जीस्ट और डैस्क प्रदर्शन की तुलना की जाती है। 8 भौतिक कोर के साथ एक I7 मशीन पर, मुझे X4 गुना स्पीडअप मिला। मुझे यह सुनना अच्छा लगेगा कि आपको अपने वास्तविक डेटा पर क्या मिलेगा!

from time import time

if __name__ == '__main__': 
    sep = '-' * 50

    # isin test
    N = 10000000
    df = pd.DataFrame({'c1': np.random.randint(low=1, high=N, size=N), 'c2': np.arange(N)})
    lookfor = np.random.randint(low=1, high=N, size=1000000)

    print('{}\ntesting pandas isin on {}\n{}'.format(sep, df.shape, sep))
    t1 = time()
    print('result\n{}'.format(df.isin(lookfor).sum()))
    t2 = time()
    print('time for native implementation {}\n{}'.format(round(t2 - t1, 2), sep))

    t3 = time()
    res = df_multi_core(df=df, df_f_name='isin', subset=['c1'], njobs=-1, values=lookfor)
    print('result\n{}'.format(res.sum()))
    t4 = time()
    print('time for multi core implementation {}\n{}'.format(round(t4 - t3, 2), sep))


    t5 = time()
    ddata = dd.from_pandas(df, npartitions=njobs)
    res = ddata.map_partitions(lambda df: df.apply(apply_f, axis=1)).compute(scheduler='processes')
    t6 = time()
    print('result random sample\n{}'.format(res.sample(n=3, random_state=0)))
    print('time for dask implementation {}\n{}'.format(round(t6 - t5, 2), sep))

--------------------------------------------------
testing pandas isin on (10000000, 2)
--------------------------------------------------
result
c1    953213
c2    951942
dtype: int64
time for native implementation 3.87
--------------------------------------------------
result
c1    953213
dtype: int64
time for multi core implementation 1.16
--------------------------------------------------
result
c1    953213
c2    951942
dtype: int64
time for dask implementation 2.88

@Therriault के साथ मैंने एक डस्क तुलना की है isin- ऐसा लगता है कि कोड स्निपेट 'isin' के साथ सबसे प्रभावी है - ~ X1.75 गुना तेजी से तो dask ( applyफ़ंक्शन की तुलना में केवल 5% तेजी से प्राप्त किया गया तो dask)
mork
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.