NumPy ব্যবহার করে চলন্ত গড় গণনা কিভাবে করবেন?


115

এমন কোনও ফাংশন বলে মনে হচ্ছে না যা কেবল নম্পি / স্কিপিতে চলমান গড় গণনা করে, যা সংশ্লেষিত সমাধানের দিকে নিয়ে যায়

আমার প্রশ্ন দ্বিগুণ:

  • নম্পির সাথে মুভিং এভারেজ বাস্তবায়নের (সঠিকভাবে) সবচেয়ে সহজ উপায় কী?
  • যেহেতু এটি অ-তুচ্ছ এবং ত্রুটির প্রবণ বলে মনে হচ্ছে, ব্যাটারিগুলি এই ক্ষেত্রে অন্তর্ভুক্ত না করার কোনও ভাল কারণ আছে ?

19
কনভলিউশন সলিউশনটি আমার কাছে মনে হয় না যে দুর্গন্ধযুক্ত!
wim

4
মুভিং এভারেজ কি কেবল নিম্ন-পাসের ফিল্টার নয় (অর্থাত্ 'অস্পষ্টতা')? খুব নিশ্চিত যে ঠিক সেই ধরণের জিনিসটি
বোঝার

@ মিমজিপি আমি অনুমান করি যে আমি ভুল বলে আশাবাদী ছিলাম, বা এটির একটি ভাল, সুস্পষ্ট কারণ ছিল।
goncalopp

4
@ উইম এটি একটি শ্লেষ হিসাবে অর্ধনির্ভর ছিল। তবে প্রশ্নটি বিদ্যমান যে নিছক সত্যটির অর্থ হ'ল numpy.convolve থেকে চলমান গড় তৈরি করা সোজা নয়।
goncalopp

উত্তর:


174

আপনি শুধুমাত্র একটি সহজবোধ্য চান অ পরিমেয় গড় চলন্ত, আপনি সহজেই এটি সঙ্গে বাস্তবায়ন করতে পারে np.cumsum, যা হতে পারে হল দ্রুত FFT চেয়ে ভিত্তিক পদ্ধতি:

সম্পাদনা কোডটিতে বিন দ্বারা চিহ্নিত একটি অফ বাই এক ভুল সূচক সংশোধন করেছে। সম্পাদনা

def moving_average(a, n=3) :
    ret = np.cumsum(a, dtype=float)
    ret[n:] = ret[n:] - ret[:-n]
    return ret[n - 1:] / n

>>> a = np.arange(20)
>>> moving_average(a)
array([  1.,   2.,   3.,   4.,   5.,   6.,   7.,   8.,   9.,  10.,  11.,
        12.,  13.,  14.,  15.,  16.,  17.,  18.])
>>> moving_average(a, n=4)
array([  1.5,   2.5,   3.5,   4.5,   5.5,   6.5,   7.5,   8.5,   9.5,
        10.5,  11.5,  12.5,  13.5,  14.5,  15.5,  16.5,  17.5])

সুতরাং আমি অনুমান করি উত্তরটি হ'ল: এটি বাস্তবায়ন করা সত্যিই সহজ, এবং সম্ভবত স্পষ্টতই বিশেষায়িত কার্যকারিতা সহ কিছুটা স্ফীত।


12
এই কোডটি ভুল। উদাহরণস্বরূপ মুভিং_ভেজেজ ([1,2,5,10], n = 2) [1., 3.5, 8.5] দেয়। এমনকি 0 থেকে 19 মানের চলমান গড়ের জন্য উত্তরদাতার পরীক্ষার কেসটিও ভুল, দাবী করে যে 0, 1 এবং 2 এর গড় গড়ে 0.5। এটি কীভাবে 6 টি উপভোগ পেয়েছিল?
জেরেমিকুন

4
বাগ চেকিংয়ের জন্য ধন্যবাদ, এখন এটি ঠিকঠাক কাজ করছে বলে মনে হচ্ছে। Upvotes হিসাবে, আমি উত্তর পিছনে সাধারণ ধারণা বাস্তবায়নের একটি বাই বাই ওয়ান ত্রুটি চেয়ে বেশি ভারী ওজন ছিল অনুমান করা হয়, কিন্তু কে জানে।
জাইমে

4
আমি সমস্যা পাওয়া। ret[n:] -= ret[:-n]হিসাবে একই নয় ret[n:] = ret[n:] - ret[:-n]। আমি এই উত্তরে কোডটি স্থির করেছি। সম্পাদনা: নাহ, আর কেউ আমাকে খালি মারেনি।
টিম্ম্ম্ম

8
@ টিএমএমএম আমি করেছিলাম, এটি আসলে সমস্যা ছিল। এই উত্তরের পিছনে সাধারণ নীতিটি ইমেজ প্রসেসিংয়ে ব্যাপকভাবে ব্যবহৃত হয় (সংক্ষিপ্ত অঞ্চল টেবিলগুলি তারা এটি বলে), তাই বিষয়টি বাস্তবায়নের ক্ষেত্রে থাকতে হয়েছিল। অকাল অপটিমাইজেশন দ্বারা বিট হওয়ার একটি ভাল উদাহরণ, যেহেতু আমি একধরণের অপারেশনটি জায়গায় রেখে করছি "কারণ এটি আরও দক্ষ হবে" " উজ্জ্বল দিকে, এটি সম্ভবত ভুল উত্তরটি দ্রুত তৈরি করেছিল ...
Jaime

46
হুম, মনে হচ্ছে এটি "কার্যকর করা সহজ" ফাংশনটি ভুল হওয়া খুব সহজ এবং মেমরির দক্ষতার উপর একটি ভাল আলোচনার জন্ম দিয়েছে। আমি ফুলে ফুলে খুশি, যদি এর অর্থ হল যে কোনও কিছু সঠিকভাবে করা হয়েছে তা জেনে।
রিচার্ড

82

নুমপির কোনও নির্দিষ্ট ডোমেন-সুনির্দিষ্ট ক্রিয়াকলাপের অভাব সম্ভবত নূমপির মূল নির্দেশের জন্য কোর টিমের শৃঙ্খলা এবং বিশ্বস্ততার কারণে: একটি এন-ডাইমেনশনাল অ্যারে প্রকারের পাশাপাশি সেই অ্যারেগুলি তৈরি এবং সূচীকরণের জন্য কার্যাদি সরবরাহ করে। অনেকগুলি মূল লক্ষ্যগুলির মতো, এটিও ছোট নয়, এবং নুমপি এটি দুর্দান্তভাবে সম্পাদন করে।

(অনেক) বৃহত্তর SciPy ডোমেন-নির্দিষ্ট গ্রন্থাগারগুলির একটি বৃহত্তর সংগ্রহ (যা সাইপাই ডেভস দ্বারা সাবপ্যাকেজ নামে পরিচিত ) রয়েছে - উদাহরণস্বরূপ, সংখ্যাসূচক অপ্টিমাইজেশন ( অনুকূলিতকরণ ), সংকেত প্রসেসিং ( সংকেত ), এবং ইন্টিগ্রাল ক্যালকুলাস ( সংহত )।

আমার অনুমান যে আপনি যে ফাংশনটি করছেন তা হ'ল কমপক্ষে একটি সাইপাই সাবপ্যাকেজ ( স্কিপি.সাইনাল সম্ভবত) এর মধ্যে রয়েছে; যাইহোক, আমি বিজ্ঞান বিজ্ঞানের সংগ্রহগুলিতে প্রথমে নজর দেব, প্রাসঙ্গিক সাইকিট (গুলি) সনাক্ত করুন এবং সেখানে আগ্রহের কার্যকারিতা সন্ধান করব।

সায়কিটস স্বাধীনভাবে নুমপি / সাইপাইয়ের উপর ভিত্তি করে প্যাকেজগুলি বিকাশিত হয় এবং নির্দিষ্ট প্রযুক্তিগত অনুশাসনের দিকে পরিচালিত হয় (উদাহরণস্বরূপ, সাইকিটস-ইমেজ , সাইকিটস-লার্নিং ইত্যাদি) এর মধ্যে বেশ কয়েকটি ছিল (বিশেষত, সংখ্যাসূচক অপ্টিমাইজেশনের জন্য দুর্দান্ত ওপেনঅ্যাপ ) অত্যন্ত সম্মানিত, তুলনামূলকভাবে নতুন সায়কিটস রুব্রিকের অধীনে বাস করা বাছাই করার আগে অনেক আগে পরিপক্ক প্রকল্পগুলি । Scikits 30 যেমন সম্পর্কে উপরে তালিকাতে পছন্দ হোমপেজে scikits , যদিও অন্তত যারা বিভিন্ন সক্রিয় উন্নয়ন অধীনে এখন আর নেই।

এই পরামর্শ অনুসরণ করে আপনি বিজ্ঞান - সময়শ্রেণীতে যেতে হবে ; তবে, সেই প্যাকেজটি এখন সক্রিয় বিকাশের অধীনে নেই; ফলস্বরূপ, পান্ডাস আফিমিকে পরিণত হয়েছে, ডি ফ্যাক্টো নুমপাই ভিত্তিক সময় সিরিজের লাইব্রেরি।

পান্ডার বেশ কয়েকটি ফাংশন রয়েছে যা চলন গড় গণনা করতে ব্যবহার করা যেতে পারে ; এর মধ্যে সরলতমটি সম্ভবত রোলিং_মিন , যা আপনি এর মতো ব্যবহার করেন:

>>> # the recommended syntax to import pandas
>>> import pandas as PD
>>> import numpy as NP

>>> # prepare some fake data:
>>> # the date-time indices:
>>> t = PD.date_range('1/1/2010', '12/31/2012', freq='D')

>>> # the data:
>>> x = NP.arange(0, t.shape[0])

>>> # combine the data & index into a Pandas 'Series' object
>>> D = PD.Series(x, t)

এখন, কেবল সিরিজ অবজেক্টে একটি ফাংশন রোলিং_মিন এবং একটি উইন্ডো আকারে কল করুন যা নীচের আমার উদাহরণে 10 দিন

>>> d_mva = PD.rolling_mean(D, 10)

>>> # d_mva is the same size as the original Series
>>> d_mva.shape
    (1096,)

>>> # though obviously the first w values are NaN where w is the window size
>>> d_mva[:3]
    2010-01-01         NaN
    2010-01-02         NaN
    2010-01-03         NaN

এটি কার্যকর হয়েছে কিনা তা যাচাই করুন - উদাহরণস্বরূপ, নতুন সিরিজ বনাম মূল সিরিজের তুলনায় 10 - 15 এর তুলনায় মানগুলি ঘূর্ণায়মান গড়ের সাথে স্মুথড

>>> D[10:15]
     2010-01-11    2.041076
     2010-01-12    2.041076
     2010-01-13    2.720585
     2010-01-14    2.720585
     2010-01-15    3.656987
     Freq: D

>>> d_mva[10:20]
      2010-01-11    3.131125
      2010-01-12    3.035232
      2010-01-13    2.923144
      2010-01-14    2.811055
      2010-01-15    2.785824
      Freq: D

প্রায় এক ডজন বা অন্যান্য ফাংশনটি রোলিং_মিনের সাথে অনানুষ্ঠানিকভাবে পান্ডাস ডকুমেন্টেশনে রুব্রিক মুভিং উইন্ডো ফাংশনের অধীনে দলবদ্ধ করা হয়েছে ; পান্ডাসে একটি দ্বিতীয়, সম্পর্কিত গ্রুপের কার্যকে তাত্পর্যপূর্ণ ওজনযুক্ত ফাংশন হিসাবে চিহ্নিত করা হয় (যেমন, ইওমা , যা তাত্পর্যপূর্ণভাবে চলমান ওজন গড়কে গণনা করে)। এই দ্বিতীয় গ্রুপটি প্রথমটি ( চলমান উইন্ডো ফাংশন) এর অন্তর্ভুক্ত না হওয়ার কারণ সম্ভবত তাত্পর্যযুক্ত ওজনযুক্ত রূপান্তরগুলি একটি নির্দিষ্ট দৈর্ঘ্যের উইন্ডোর উপর নির্ভর করে না


7
পান্ডাসের উইন্ডো ফাংশনগুলিতে চলমান শক্তিশালী রেখা রয়েছে। তবে সরল গড়ের গড়ের জন্য আমার কাছে এটি খুব বেশি ওভারহেডের মতো মনে হয়।
জাইমে

7
আমি সন্দেহ করি যে চলন্ত গড় গণনা করা ওপি বা অন্য কারও জন্য বিচ্ছিন্ন প্রয়োজন। যদি আপনার চলমান গড় গণনা করতে হয় তবে আপনার কাছে অবশ্যই একটি সময় সিরিজ রয়েছে যার অর্থ আপনার একটি ডেটা কাঠামো দরকার যা আপনাকে আপনার ডেটাতে একটি তারিখ-সময় সূচী অনুসারে মঞ্জুরি দেয় এবং এটিই 'ওভারহেড' আপনি উল্লেখ করেন।
ডাব

4
প্রথমত, এই অত্যন্ত তথ্যবহুল উত্তরটি লেখার জন্য সময় দেওয়ার জন্য আপনাকে ধন্যবাদ। প্রকৃতপক্ষে, আমি চলমান গড়ের জন্য এমন কোনও ব্যবহার দেখতে পাচ্ছি না যা কোনও সময়ের সিরিজ জড়িত না। তবে এর অর্থ এই নয় যে একজনকে এটি একটি তারিখের সময় বা এমনকি একটি নির্দিষ্ট নমুনার ব্যবধানে (এটি অজানা হতে পারে) সাথে সামঞ্জস্য করা দরকার
goncalopp

4
কেবল যোগ করতে চেয়েছিলেন যে চলন্ত গড় ফাংশনটি বোতলনেক লাইব্রেরিতে বের করা হয়েছে যদি পান্ডগুলি নির্ভরতা হিসাবে খুব বেশি ভারী ওজন বলে মনে হয়।
রোবচ্যাট

4
'রোলিং_মিয়ান' আর পিএফ পান্ডসের অংশ নয়, দয়া করে পরিবর্তে 'রোলিং' ব্যবহার করে উত্তর দেখুন
ভ্লাদ্টন

76

এটি অর্জনের একটি সহজ উপায় হ'ল ব্যবহার করে np.convolve। এর পেছনের ধারণাটি হ'ল পৃথক সমঝোতাটি গণনা করার পদ্ধতিটি উত্তোলন করা এবং এটি ঘূর্ণায়মান গড় ফেরত দিতে ব্যবহার করা । np.onesআমরা যে স্লাইডিং উইন্ডো দৈর্ঘ্য চাই তার সমান দৈর্ঘ্যের ক্রম সহ একত্রিত করে এটি করা যেতে পারে ।

এটি করার জন্য আমরা নিম্নলিখিত ফাংশনটি সংজ্ঞায়িত করতে পারি:

def moving_average(x, w):
    return np.convolve(x, np.ones(w), 'valid') / w

এই ফাংশনটি অনুক্রমের কনভোলশন xএবং দৈর্ঘ্যের দিকগুলির ক্রম গ্রহণ করবে w। নোট করুন যে নির্বাচিতটি modeএমন validযাতে কনভোলশন পণ্যটি কেবল এমন পয়েন্টগুলির জন্য দেওয়া হয় যেখানে ক্রমগুলি সম্পূর্ণরূপে ওভারল্যাপ করে।


কিছু উদাহরণ:

x = np.array([5,3,8,10,2,1,5,1,0,2])

দৈর্ঘ্যের একটি উইন্ডো সহ চলন্ত গড়ের জন্য 2আমাদের কাছে:

moving_average(x, 2)
# array([4. , 5.5, 9. , 6. , 1.5, 3. , 3. , 0.5, 1. ])

দৈর্ঘ্যের একটি উইন্ডো জন্য 4 :

moving_average(x, 4)
# array([6.5 , 5.75, 5.25, 4.5 , 2.25, 1.75, 2.  ])

কিভাবে convolveকাজ করে?

যেভাবে পৃথক সমঝোতা গণনা করা হচ্ছে তার আরও গভীরভাবে নজর দেওয়া যাক। নিম্নলিখিত ফাংশনটি np.convolveআউটপুট মানগুলি গণনা করে সেই উপায়টির প্রতিলিপি তৈরির লক্ষ্য রয়েছে :

def mov_avg(x, w):
    for m in range(len(x)-(w-1)):
        yield sum(np.ones(w) * x[m:m+w]) / w 

যা উপরের একই উদাহরণের জন্যও ফল দেয়:

list(mov_avg(x, 2))
# [4.0, 5.5, 9.0, 6.0, 1.5, 3.0, 3.0, 0.5, 1.0]

সুতরাং প্রতিটি পদক্ষেপে যা করা হচ্ছে তা হ'ল অভ্যন্তরীণ পণ্যটিকে অ্যারের এবং বর্তমান উইন্ডোর মধ্যে নেওয়া । এই ক্ষেত্রে গুণ দ্বারাnp.ones(w) অতিমাত্রায় হয় যে আমরা সরাসরি sumক্রমটি নিচ্ছি ।

বেলো প্রথম আউটপুটগুলি কীভাবে গণনা করা হয় তার একটি উদাহরণ যাতে এটি আরও পরিষ্কার হয়। ধরা যাক আমরা একটি উইন্ডো চাইw=4 :

[1,1,1,1]
[5,3,8,10,2,1,5,1,0,2]
= (1*5 + 1*3 + 1*8 + 1*10) / w = 6.5

এবং নিম্নলিখিত আউটপুট হিসাবে গণনা করা হবে:

  [1,1,1,1]
[5,3,8,10,2,1,5,1,0,2]
= (1*3 + 1*8 + 1*10 + 1*2) / w = 5.75

এবং এরপরে, সমস্ত ওভারল্যাপ সম্পাদিত হয়ে গেলে ক্রমটির চলমান গড় ফিরে পাওয়া।


4
এটি একটি দুর্দান্ত ধারণা! এটি ছোট এন এর জন্য জাইমের উত্তর চেয়ে দ্রুত, তবে বৃহত্তর এন এর জন্য ধীর হয়ে যায়।
ফিলিপ জেরার্ড 14

ধন্যবাদ @ ফিলিপগার্ড! হ্যাঁ মন্তব্যে নির্দেশিত হিসাবে, যদিও এই পদ্ধতিটি অন্য কিছু নালিশ সমাধানগুলির মতো দক্ষ নাও হতে পারে তবে ইমো এটির সরলতা এবং স্বচ্ছলতার কারণে ভবিষ্যতের দর্শকদের জন্য বিকল্প হিসাবে ভাল লাগবে
ইয়াতু

4
কখনও কখনও এটি ইনপুট হিসাবে একই আকার আউটপুট অ্যারে থাকা দরকারী। এটির জন্য mode='valid'প্রতিস্থাপন করা যেতে পারে 'same'। এই ক্ষেত্রে প্রান্ত পয়েন্টগুলি শূন্যের দিকে মহাকর্ষ হবে।
ইলিয়া বারাহোভস্কি 20

এমন পরিস্থিতিতে যেখানে ফাংশনের অ্যারে 'x' এর কিছু উপাদান কোনও বা শূন্য হতে পারে, আপনি এই ফাংশন থেকে ফিরে পাওয়া মানগুলির সাথে সম্পর্কিত 'x' মানগুলি কীভাবে পাবেন? এই ফাংশন থেকে ফিরে আসা অ্যারের আকার এটি সরবরাহ করা অ্যারে 'x' এর চেয়ে ছোট হতে পারে।
সান বিয়ার

18

কিছু মানদণ্ড সহ এটি করার বিভিন্ন উপায় এখানে রয়েছে। সর্বোত্তম পদ্ধতি হ'ল অন্যান্য লাইব্রেরি থেকে অনুকূলিত কোড ব্যবহার করে সংস্করণ। bottleneck.move_meanপদ্ধতি সম্ভবত শ্রেষ্ঠ সব প্রায়। scipy.convolveপদ্ধতির খুব দ্রুত, প্রসার্য এবং চিহ্নগুলি সিন্টেক্সের এবং ধারণার দিক থেকে সহজ, কিন্তু খুব বড় জানালা মানের জন্য ভাল স্কেল নেই। numpy.cumsumআপনার যদি খাঁটি numpyপদ্ধতির প্রয়োজন হয় তবে পদ্ধতিটি ভাল ।

দ্রষ্টব্য: এর মধ্যে কয়েকটি (উদাঃ bottleneck.move_mean) কেন্দ্রিক নয় এবং আপনার ডেটা স্থানান্তর করবে।

import numpy as np
import scipy as sci
import scipy.signal as sig
import pandas as pd
import bottleneck as bn
import time as time

def rollavg_direct(a,n): 
    'Direct "for" loop'
    assert n%2==1
    b = a*0.0
    for i in range(len(a)) :
        b[i]=a[max(i-n//2,0):min(i+n//2+1,len(a))].mean()
    return b

def rollavg_comprehension(a,n):
    'List comprehension'
    assert n%2==1
    r,N = int(n/2),len(a)
    return np.array([a[max(i-r,0):min(i+r+1,N)].mean() for i in range(N)]) 

def rollavg_convolve(a,n):
    'scipy.convolve'
    assert n%2==1
    return sci.convolve(a,np.ones(n,dtype='float')/n, 'same')[n//2:-n//2+1]  

def rollavg_convolve_edges(a,n):
    'scipy.convolve, edge handling'
    assert n%2==1
    return sci.convolve(a,np.ones(n,dtype='float'), 'same')/sci.convolve(np.ones(len(a)),np.ones(n), 'same')  

def rollavg_cumsum(a,n):
    'numpy.cumsum'
    assert n%2==1
    cumsum_vec = np.cumsum(np.insert(a, 0, 0)) 
    return (cumsum_vec[n:] - cumsum_vec[:-n]) / n

def rollavg_cumsum_edges(a,n):
    'numpy.cumsum, edge handling'
    assert n%2==1
    N = len(a)
    cumsum_vec = np.cumsum(np.insert(np.pad(a,(n-1,n-1),'constant'), 0, 0)) 
    d = np.hstack((np.arange(n//2+1,n),np.ones(N-n)*n,np.arange(n,n//2,-1)))  
    return (cumsum_vec[n+n//2:-n//2+1] - cumsum_vec[n//2:-n-n//2]) / d

def rollavg_roll(a,n):
    'Numpy array rolling'
    assert n%2==1
    N = len(a)
    rolling_idx = np.mod((N-1)*np.arange(n)[:,None] + np.arange(N), N)
    return a[rolling_idx].mean(axis=0)[n-1:] 

def rollavg_roll_edges(a,n):
    # see /programming/42101082/fast-numpy-roll
    'Numpy array rolling, edge handling'
    assert n%2==1
    a = np.pad(a,(0,n-1-n//2), 'constant')*np.ones(n)[:,None]
    m = a.shape[1]
    idx = np.mod((m-1)*np.arange(n)[:,None] + np.arange(m), m) # Rolling index
    out = a[np.arange(-n//2,n//2)[:,None], idx]
    d = np.hstack((np.arange(1,n),np.ones(m-2*n+1+n//2)*n,np.arange(n,n//2,-1)))
    return (out.sum(axis=0)/d)[n//2:]

def rollavg_pandas(a,n):
    'Pandas rolling average'
    return pd.DataFrame(a).rolling(n, center=True, min_periods=1).mean().to_numpy()

def rollavg_bottlneck(a,n):
    'bottleneck.move_mean'
    return bn.move_mean(a, window=n, min_count=1)

N = 10**6
a = np.random.rand(N)
functions = [rollavg_direct, rollavg_comprehension, rollavg_convolve, 
        rollavg_convolve_edges, rollavg_cumsum, rollavg_cumsum_edges, 
        rollavg_pandas, rollavg_bottlneck, rollavg_roll, rollavg_roll_edges]

print('Small window (n=3)')
%load_ext memory_profiler
for f in functions : 
    print('\n'+f.__doc__+ ' : ')
    %timeit b=f(a,3)

print('\nLarge window (n=1001)')
for f in functions[0:-2] : 
    print('\n'+f.__doc__+ ' : ')
    %timeit b=f(a,1001)

print('\nMemory\n')
print('Small window (n=3)')
N = 10**7
a = np.random.rand(N)
%load_ext memory_profiler
for f in functions[2:] : 
    print('\n'+f.__doc__+ ' : ')
    %memit b=f(a,3)

print('\nLarge window (n=1001)')
for f in functions[2:-2] : 
    print('\n'+f.__doc__+ ' : ')
    %memit b=f(a,1001)

সময়, ছোট উইন্ডো (n = 3)

Direct "for" loop : 

4.14 s ± 23.7 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

List comprehension : 
3.96 s ± 27.9 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

scipy.convolve : 
1.07 ms ± 26.7 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

scipy.convolve, edge handling : 
4.68 ms ± 9.69 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

numpy.cumsum : 
5.31 ms ± 5.11 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

numpy.cumsum, edge handling : 
8.52 ms ± 11.1 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

Pandas rolling average : 
9.85 ms ± 9.63 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

bottleneck.move_mean : 
1.3 ms ± 12.2 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

Numpy array rolling : 
31.3 ms ± 91.9 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

Numpy array rolling, edge handling : 
61.1 ms ± 55.9 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

সময়, বড় উইন্ডো (n = 1001)

Direct "for" loop : 
4.67 s ± 34 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

List comprehension : 
4.46 s ± 14.6 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

scipy.convolve : 
103 ms ± 165 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

scipy.convolve, edge handling : 
272 ms ± 1.23 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

numpy.cumsum : 
5.19 ms ± 12.4 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

numpy.cumsum, edge handling : 
8.7 ms ± 11.5 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

Pandas rolling average : 
9.67 ms ± 199 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

bottleneck.move_mean : 
1.31 ms ± 15.7 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

স্মৃতি, ছোট উইন্ডো (n = 3)

The memory_profiler extension is already loaded. To reload it, use:
  %reload_ext memory_profiler

scipy.convolve : 
peak memory: 362.66 MiB, increment: 73.61 MiB

scipy.convolve, edge handling : 
peak memory: 510.24 MiB, increment: 221.19 MiB

numpy.cumsum : 
peak memory: 441.81 MiB, increment: 152.76 MiB

numpy.cumsum, edge handling : 
peak memory: 518.14 MiB, increment: 228.84 MiB

Pandas rolling average : 
peak memory: 449.34 MiB, increment: 160.02 MiB

bottleneck.move_mean : 
peak memory: 374.17 MiB, increment: 75.54 MiB

Numpy array rolling : 
peak memory: 661.29 MiB, increment: 362.65 MiB

Numpy array rolling, edge handling : 
peak memory: 1111.25 MiB, increment: 812.61 MiB

স্মৃতি, বড় উইন্ডো (n = 1001)

scipy.convolve : 
peak memory: 370.62 MiB, increment: 71.83 MiB

scipy.convolve, edge handling : 
peak memory: 521.98 MiB, increment: 223.18 MiB

numpy.cumsum : 
peak memory: 451.32 MiB, increment: 152.52 MiB

numpy.cumsum, edge handling : 
peak memory: 527.51 MiB, increment: 228.71 MiB

Pandas rolling average : 
peak memory: 451.25 MiB, increment: 152.50 MiB

bottleneck.move_mean : 
peak memory: 374.64 MiB, increment: 75.85 MiB

11

পান্ডাস ব্যবহার করে এই উত্তর উপরের দিক থেকে অভিযোজিত, যেহেতু rolling_meanআর পান্ডসের অংশ নয়

# the recommended syntax to import pandas
import pandas as pd
import numpy as np

# prepare some fake data:
# the date-time indices:
t = pd.date_range('1/1/2010', '12/31/2012', freq='D')

# the data:
x = np.arange(0, t.shape[0])

# combine the data & index into a Pandas 'Series' object
D = pd.Series(x, t)

এখন, কেবল rollingউইন্ডো আকারের সাথে ডেটাফ্রেমে ফাংশনটি কল করুন , যা নীচে আমার উদাহরণে 10 দিন।

d_mva10 = D.rolling(10).mean()

# d_mva is the same size as the original Series
# though obviously the first w values are NaN where w is the window size
d_mva10[:11]

2010-01-01    NaN
2010-01-02    NaN
2010-01-03    NaN
2010-01-04    NaN
2010-01-05    NaN
2010-01-06    NaN
2010-01-07    NaN
2010-01-08    NaN
2010-01-09    NaN
2010-01-10    4.5
2010-01-11    5.5
Freq: D, dtype: float64

5

আমি মনে করি এটি খুব সহজেই বাধা ব্যবহার করে সমাধান করা যেতে পারে

নীচে বেসিক নমুনা দেখুন:

import numpy as np
import bottleneck as bn

a = np.random.randint(4, 1000, size=(5, 7))
mm = bn.move_mean(a, window=2, min_count=1)

এটি প্রতিটি অক্ষ বরাবর সরানো দেয়।

  • "মিমি" হ'ল "এ" এর চলন্ত গড়।

  • "উইন্ডো" হ'ল চলমান গড়ের জন্য বিবেচনার জন্য সর্বাধিক সংখ্যা ries

  • "মিনি_কাউন্ট" হ'ল চলমান গড়ের জন্য বিবেচ্য ন্যূনতম এন্ট্রি (উদাহরণস্বরূপ প্রথম উপাদানটির জন্য বা অ্যারের যদি ন্যানের মান থাকে)।

ভাল অংশ হ'ল বোতলেনেক ন্যান মানগুলি মোকাবেলা করতে সহায়তা করে এবং এটি খুব দক্ষ।


2

আপনি যদি প্রান্ত শর্তাদি যত্ন সহকারে যত্ন নিতে চান ( গণনাটি কেবলমাত্র প্রান্তগুলিতে উপলব্ধ উপাদানগুলির দ্বারা গণ্য হয়), নিম্নলিখিত ফাংশনটি কৌশলটি করবে।

import numpy as np

def running_mean(x, N):
    out = np.zeros_like(x, dtype=np.float64)
    dim_len = x.shape[0]
    for i in range(dim_len):
        if N%2 == 0:
            a, b = i - (N-1)//2, i + (N-1)//2 + 2
        else:
            a, b = i - (N-1)//2, i + (N-1)//2 + 1

        #cap indices to min and max indices
        a = max(0, a)
        b = min(dim_len, b)
        out[i] = np.mean(x[a:b])
    return out

>>> running_mean(np.array([1,2,3,4]), 2)
array([1.5, 2.5, 3.5, 4. ])

>>> running_mean(np.array([1,2,3,4]), 3)
array([1.5, 2. , 3. , 3.5])

1
for i in range(len(Data)):
    Data[i, 1] = Data[i-lookback:i, 0].sum() / lookback

এই টুকরা কোড ব্যবহার করে দেখুন। আমি মনে করি এটি সহজ এবং কাজটি করে। লুকব্যাক হ'ল চলমান গড়ের উইন্ডো।

ইন Data[i-lookback:i, 0].sum()আমি করা আছে 0ডেটা সেটটি প্রথম কলামে উল্লেখ করতে কিন্তু আপনি যদি আপনার মত যেকোনো কলাম লাগাতে পারেন আপনার চেয়ে আরো একটি কলাম আছে।


1

চলন্ত গড়

পুনরুক্তি পদ্ধতি

  • অ্যারে বিপরীত করুন, এবং কেবল i থেকে n এ গড়টি নিন।

  • ফ্লাইতে মিনি অ্যারে তৈরি করতে তালিকা বোঝার ব্যবহার করুন।

x = np.random.randint(10, size=20)

def moving_average(arr, n):
    return [ (arr[:i+1][::-1][:n]).mean() for i, ele in enumerate(arr) ]
d = 5

moving_average(x, d)

টেনসর সমঝোতা

moving_average = np.convolve(x, np.ones(d)/d, mode='valid')

0

আমি স্বীকৃত উত্তরের চেয়ে কিছুটা আলাদা আচরণ চাইছিলাম wanted আমি sklearnপাইপলাইনের জন্য মুভিং এভারেজ ফিচার এক্সট্রাক্টর তৈরি করছিলাম, সুতরাং আমার প্রয়োজন ছিল যে মুভিং এভারেজের আউটপুটটির ইনপুটটির মতো একই মাত্রা থাকবে। আমি যা চাই তা হল চলমান গড় ধরে নেওয়া সিরিজটি ধরে রাখা স্থির থাকে, অর্থাৎ [1,2,3,4,5]উইন্ডো 2 সহ একটি চলমান গড় দেবে [1.5,2.5,3.5,4.5,5.0]

কলামের ভেক্টরগুলির জন্য (আমার ব্যবহারের ক্ষেত্রে) আমরা পাই

def moving_average_col(X, n):
  z2 = np.cumsum(np.pad(X, ((n,0),(0,0)), 'constant', constant_values=0), axis=0)
  z1 = np.cumsum(np.pad(X, ((0,n),(0,0)), 'constant', constant_values=X[-1]), axis=0)
  return (z1-z2)[(n-1):-1]/n

এবং অ্যারে জন্য

def moving_average_array(X, n):
  z2 = np.cumsum(np.pad(X, (n,0), 'constant', constant_values=0))
  z1 = np.cumsum(np.pad(X, (0,n), 'constant', constant_values=X[-1]))
  return (z1-z2)[(n-1):-1]/n

অবশ্যই, প্যাডিংয়ের জন্য একটি ধ্রুবক মান ধরে নিতে হবে না, তবে এটি করা বেশিরভাগ ক্ষেত্রে পর্যাপ্ত হওয়া উচিত।


0

তালিবের মধ্যে একটি সরল গড় চলমান গড় সরঞ্জাম রয়েছে, পাশাপাশি অন্যান্য অনুরূপ গড় সরঞ্জামগুলি (যেমন তাত্পর্যমূলক চলমান গড়)। নীচে অন্য কয়েকটি সমাধানের সাথে পদ্ধতির তুলনা করা হয়েছে।


%timeit pd.Series(np.arange(100000)).rolling(3).mean()
2.53 ms ± 40.5 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

%timeit talib.SMA(real = np.arange(100000.), timeperiod = 3)
348 µs ± 3.5 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

%timeit moving_average(np.arange(100000))
638 µs ± 45.1 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

একটি সতর্কতাই হ'ল আসলটির অবশ্যই উপাদান থাকা উচিত dtype = float। অন্যথায় নিম্নলিখিত ত্রুটি উত্থাপিত হয়

ব্যতিক্রম: আসল দ্বিগুণ নয়


0

এখানে নাম্বা (ধরণের ধরণগুলি) ব্যবহার করে দ্রুত প্রয়োগ করা হচ্ছে। মনে রাখবেন এতে নান রয়েছে যেখানে স্থানান্তরিত হয়েছে।

import numpy as np
import numba as nb

@nb.jit(nb.float64[:](nb.float64[:],nb.int64),
        fastmath=True,nopython=True)
def moving_average( array, window ):    
    ret = np.cumsum(array)
    ret[window:] = ret[window:] - ret[:-window]
    ma = ret[window - 1:] / window
    n = np.empty(window-1); n.fill(np.nan)
    return np.concatenate((n.ravel(), ma.ravel())) 

এটি শুরুতে ন্যানগুলি ফেরত দেয়।
অ্যাডাম এরিকসন

0

আমি হয় হয় গৃহীত উত্তরের সমাধানটি, ইনপুট হিসাবে আউটপুটের জন্য একই দৈর্ঘ্যের জন্য সামান্য সংশোধিত, বা pandasঅন্য উত্তরের মন্তব্যে উল্লিখিত সংস্করণটি ব্যবহার করি। আমি এখানে উভয়ের সংক্ষিপ্ত বিবরণ ভবিষ্যতের রেফারেন্সের জন্য পুনরুত্পাদনযোগ্য উদাহরণ সহ:

import numpy as np
import pandas as pd

def moving_average(a, n):
    ret = np.cumsum(a, dtype=float)
    ret[n:] = ret[n:] - ret[:-n]
    return ret / n

def moving_average_centered(a, n):
    return pd.Series(a).rolling(window=n, center=True).mean().to_numpy()

A = [0, 0, 1, 2, 4, 5, 4]
print(moving_average(A, 3))    
# [0.         0.         0.33333333 1.         2.33333333 3.66666667 4.33333333]
print(moving_average_centered(A, 3))
# [nan        0.33333333 1.         2.33333333 3.66666667 4.33333333 nan       ]

0

নীচের সমাধানটির সাথে তুলনামূলকভাবে যে নিম্পির চামসাম ব্যবহার করে, এটি প্রায় অর্ধেক সময় নেয় । এটি cumsum করতে এবং তারপরে সমস্ত বিয়োগফলটি করার জন্য পুরো অ্যারেটি দিয়ে যাওয়ার প্রয়োজন হয় না। তবুও , অ্যারেগুলি বিশাল এবং সংখ্যাটি বিশাল ( সম্ভাব্য ওভারফ্লো ) হলে চামসাম " বিপজ্জনক " হতে পারে । অবশ্যই, এখানেও বিপদ বিদ্যমান তবে কমপক্ষে কেবলমাত্র প্রয়োজনীয় সংখ্যাগুলি সংযুক্ত করা হয়।

def moving_average(array_numbers, n):
    if n > len(array_numbers):
      return []
    temp_sum = sum(array_numbers[:n])
    averages = [temp_sum / float(n)]
    for first_index, item in enumerate(array_numbers[n:]):
        temp_sum += item - array_numbers[first_index]
        averages.append(temp_sum / float(n))
    return averages
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.