किसी के लिए जो अपने कस्टम समानांतर पांडा-कोड कोड पर tqdm लागू करना चाहते हैं।
(मैंने पिछले कुछ वर्षों में समानांतरकरण के लिए कुछ पुस्तकालयों की कोशिश की, लेकिन मुझे कभी भी 100% समानांतर समाधान नहीं मिला, मुख्य रूप से लागू फ़ंक्शन के लिए, और मुझे हमेशा अपने "मैनुअल" कोड के लिए वापस आना पड़ा।)
df_multi_core - यह वह है जिसे आप कॉल करते हैं। यह स्वीकार करता है:
- आपकी df ऑब्जेक्ट
- वह फ़ंक्शन नाम जिसे आप कॉल करना चाहते हैं
- स्तंभों के सबसेट को फ़ंक्शन पर किया जा सकता है (समय / मेमोरी कम करने में मदद करता है)
- समानांतर में चलने वाली नौकरियों की संख्या (-1 या सभी कोर के लिए छोड़ दें)
- कोई भी अन्य 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 tqdm "progress_apply" के साथ समानांतर लागू होने के लिए एक परीक्षण कोड है ।
from time import time
from tqdm import tqdm
tqdm.pandas()
if __name__ == '__main__':
sep = '-' * 50
# tqdm progress_apply test
def apply_f(row):
return row['c1'] + 0.1
N = 1000000
np.random.seed(0)
df = pd.DataFrame({'c1': np.arange(N), 'c2': np.arange(N)})
print('testing pandas apply on {}\n{}'.format(df.shape, sep))
t1 = time()
res = df.progress_apply(apply_f, axis=1)
t2 = time()
print('result random sample\n{}'.format(res.sample(n=3, random_state=0)))
print('time for native implementation {}\n{}'.format(round(t2 - t1, 2), sep))
t3 = time()
# res = df_multi_core(df=df, df_f_name='apply', subset=['c1'], njobs=-1, func=apply_f, axis=1)
res = df_multi_core(df=df, df_f_name='progress_apply', subset=['c1'], njobs=-1, func=apply_f, axis=1)
t4 = time()
print('result random sample\n{}'.format(res.sample(n=3, random_state=0)))
print('time for multi core implementation {}\n{}'.format(round(t4 - t3, 2), sep))
आउटपुट में आप समानांतरकरण के बिना चलने के लिए 1 प्रगति बार देख सकते हैं, और समानांतर-चलने के साथ प्रति-कोर प्रगति बार। एक मामूली हिचप है और कभी-कभी बाकी कोर एक ही बार में दिखाई देते हैं, लेकिन फिर भी मुझे लगता है कि जब से आप प्रगति के आंकड़े प्राप्त करते हैं, तब से यह कोर (प्रति सेकंड / कुल रिकॉर्ड और पूर्व के लिए)
इस महान पुस्तकालय के लिए @abcdaa धन्यवाद!