Pandas: نافذة المتداول مع حجم الخطوة

تم إنشاؤها على ٩ فبراير ٢٠١٧  ·  38تعليقات  ·  مصدر: pandas-dev/pandas

مجرد اقتراح - قم بتوسيع rolling لدعم نافذة متدحرجة بحجم خطوة ، مثل R's rollapply(by=X) .

عينة التعليمات البرمجية

الباندا - حل غير فعال (طبق الوظيفة على كل نافذة ، ثم قم بتقطيعها للحصول على كل نتيجة ثانية)

import pandas
ts = pandas.Series(range(0, 40, 2))
ts.rolling(5).apply(max).dropna()[::2]

اقتراح:

ts = pandas.Series(range(0, 40, 2))
ts.rolling(window=5, step=2).apply(max).dropna()

مستوحى من R (انظر مستندات rollapply ):

require(zoo)
TS <- zoo(seq(0, 40, 2))
rollapply(TS, 5, FUN=max, by=2)

8 12 16 20 24 28 32 36 40

Enhancement Needs Discussion Numeric Window

التعليق الأكثر فائدة

"يمكن القيام بذلك ، لكني أرغب في رؤية حالة استخدام حيث يكون هذا مهمًا."

مهما كان المشروع الذي عملت عليه باستخدام الباندا ، فقد فاتني دائمًا هذه الميزة ، فهي مفيدة في كل مرة تحتاج فيها إلى حساب التطبيق مرة واحدة فقط من حين لآخر ولكن لا تزال بحاجة إلى دقة جيدة داخل كل نافذة.

ال 38 كومينتر

إذا كنت تستخدم وظائف "قياسية" ، فهذه دوال متجهة ، وبالتالي v سريعًا ( ts.rolling(5).max().dropna()[::2] ).

IIUC يأتي التوفير هنا من تطبيق الوظيفة فقط في جزء صغير من الوقت (على سبيل المثال كل قيمة نونية). ولكن هل هناك حالة يحدث فيها ذلك فرقًا عمليًا؟

يمكن القيام بذلك ، لكني أود أن أرى حالة استخدام حيث يكون هذا مهمًا. سيؤدي هذا إلى كسر واجهة API الخاصة بـ "إرجاع نفس حجم الإدخال" أيضًا. على الرغم من أنني لا أعتقد أن هذا صعب التنفيذ بالفعل (على الرغم من أنه سيشمل عددًا من التغييرات في التنفيذ). نحن نستخدم النوافذ الهامشية (IOW ، احسب النافذة وكلما تقدمت ، قم بإسقاط النقاط التي تغادر وأضف النقاط التي تكتسبها). لذلك لا يزال يتعين عليك حساب كل شيء ، لكنك لن تخرجه.

شكرا لردودكم!

IIUC يأتي التوفير هنا من تطبيق الوظيفة فقط في جزء صغير من الوقت (على سبيل المثال كل قيمة نونية). ولكن هل هناك حالة يحدث فيها ذلك فرقًا عمليًا؟

حالة الاستخدام الخاصة بي هي تشغيل وظائف التجميع (ليس فقط الحد الأقصى) عبر بعض أطر البيانات ذات السلسلة الزمنية الكبيرة - 400 عمود ، ساعات من البيانات عند 5-25 هرتز. لقد فعلت أيضًا شيئًا مشابهًا (هندسة الميزات على بيانات المستشعر) في الماضي ببيانات تصل إلى 20 كيلو هرتز. يؤدي تشغيل نوافذ 30 ثانية بخطوة 5 ثوانٍ إلى توفير جزء كبير من المعالجة - على سبيل المثال عند 25 هرتز بخطوة 5 ثوانٍ ، يكون 1/125 من العمل ، مما يجعل الفرق بين تشغيله في دقيقة واحدة أو ساعتين.

من الواضح أنه يمكنني الرجوع إلى numpy ، لكن سيكون من الجيد أن يكون هناك مستوى أعلى من واجهة برمجة التطبيقات للقيام بذلك. لقد اعتقدت أنه يستحق الاقتراح في حال وجده الآخرون مفيدًا أيضًا - لا أتوقع منك إنشاء ميزة لي فقط!

يمكنك محاولة إعادة أخذ العينات إلى فاصل تردد أعلى أولاً ثم التدوير

شيء مثل

df = df.resample ("30 ثانية")
df.rolling (..). max () (أو أي وظيفة)

مرحبًا jreback ، شكرًا على الاقتراح.

سيعمل هذا إذا كنت أشغل max على بياناتي (تحتاج إعادة العينة إلى وظيفة تقليل ، وإلا فإنها تكون افتراضية على mean ، أليس كذلك؟):

df.resample('1s').max().rolling(30).max()

ومع ذلك ، أود تشغيل وظيفة التخفيض الخاصة بي على 30 ثانية من البيانات ، ثم المضي قدمًا لمدة ثانية واحدة وتشغيلها في الثلاثين ثانية التالية من البيانات ، وما إلى ذلك. تطبق الطريقة أعلاه وظيفة على ثانية واحدة من البيانات ، ثم أخرى تعمل على 30 نتيجة للدالة الأولى.

إليك مثال سريع - تشغيل حساب من الذروة إلى الذروة لا يعمل مرتين (من الواضح):

# 10 minutes of data at 5Hz
n = 5 * 60 * 10
rng = pandas.date_range('1/1/2017', periods=n, freq='200ms')
np.random.seed(0)
d = np.cumsum(np.random.randn(n), axis=0)
s = pandas.Series(d, index=rng)

# Peak to peak
def p2p(d):
    return d.max() - d.min()

def p2p_arr(d):
    return d.max(axis=1) - d.min(axis=1)

def rolling_with_step(s, window, step, func):
    # See https://ga7g08.github.io/2015/01/30/Applying-python-functions-in-moving-windows/
    vert_idx_list = np.arange(0, s.size - window, step)
    hori_idx_list = np.arange(window)
    A, B = np.meshgrid(hori_idx_list, vert_idx_list)
    idx_array = A + B
    x_array = s.values[idx_array]
    idx = s.index[vert_idx_list + int(window/2.)]
    d = func(x_array)
    return pandas.Series(d, index=idx)

# Plot data
ax = s.plot(figsize=(12, 8), legend=True, label='Data')

# Plot resample then rolling (obviously does not work)
s.resample('1s').apply(p2p).rolling(window=30, center=True).apply(p2p).plot(ax=ax, label='1s p2p, roll 30 p2p', legend=True)

# Plot rolling window with step
rolling_with_step(s, window=30 * 5, step=5, func=p2p_arr).plot(ax=ax, label='Roll 30, step 1s', legend=True)

rolling window

alexlouden من الوصف الأصلي الخاص بك أعتقد شيء من هذا القبيل

df.resample('5s').max().rolling('30s').mean() (أو أي تخفيضات) أكثر انسجامًا مع ما تريد

IOW ، خذ كل ما هو في حاوية 5s ، ثم اختصره إلى نقطة واحدة ، ثم قم بتدوير هذه الصناديق. هذه الفكرة العامة هي أن لديك الكثير من البيانات التي يمكن تلخيصها في نطاق زمني قصير ، لكنك في الواقع تريد تدوير هذا على مستوى أعلى.

مرحبًا jreback ، أريد فعلاً تشغيل وظيفة تزيد عن 30 ثانية من البيانات ، كل 5 ثوانٍ. انظر إلى الدالة rolling_with_step في المثال السابق. الخطوة الإضافية من الحد الأقصى / المتوسط ​​لا تعمل مع حالة الاستخدام الخاصة بي.

jreback ، هناك حاجة حقيقية لوظيفة الخطوة التي لم تظهر في هذه المناقشة حتى الآن. أؤيد كل ما وصفتهalexlouden ، لكني أود إضافة المزيد من حالات الاستخدام.

افترض أننا نقوم بتحليل السلاسل الزمنية مع أخذ عينات من بيانات الإدخال حوالي 3 إلى 10 مللي ثانية. نحن مهتمون بميزات مجال التردد. ستكون الخطوة الأولى في بنائها هي معرفة تردد نيكويست. افترض من خلال معرفة المجال أننا نعلم أن 10 هرتز (مرة واحدة كل 100 مللي ثانية). هذا يعني أننا بحاجة إلى أن يكون تردد البيانات 20 هرتز على الأقل (مرة واحدة كل 50 مللي ثانية) ، إذا كان يجب أن تلتقط الميزات إشارة الإدخال جيدًا. لا يمكننا إعادة التشكيل لتردد أقل من ذلك. في النهاية ، ها هي الحسابات التي نقوم بها:

df.resample('50ms').mean().rolling(window=32).aggregate(power_spectrum_coeff)

هنا اخترنا حجم نافذة بمضاعفات 8 ، واختيار 32 يجعل حجم النافذة 1.6 ثانية. ترجع الدالة التجميعية معاملات مجال التردد أحادية الجانب وبدون المكون المتوسط ​​الأول (الدالة fft متماثلة وذات قيمة متوسطة عند العنصر 0). فيما يلي دالة تجميع العينة:

def power_spectrum_coeff():
    def power_spectrum_coeff_(x):
        return np.fft.fft(x)[1 : int(len(x) / 2 + 1)]

    power_spectrum_coeff_.__name__ = 'power_spectrum_coeff'
    return power_spectrum_coeff_

الآن ، نود أن نكرر هذا في نافذة انزلاقية ، لنقل كل 0.4 ثانية أو كل 0.8 ثانية. ليس هناك فائدة من إضاعة العمليات الحسابية وحساب FFT كل 50 مللي ثانية بدلاً من ذلك ثم التقطيع لاحقًا. علاوة على ذلك ، فإن إعادة التشكيل حتى 400 مللي ثانية ليس خيارًا ، لأن 400 مللي ثانية هي 2.5 هرتز فقط ، وهو أقل بكثير من تردد نيكويست ، والقيام بذلك سيؤدي إلى فقد جميع المعلومات من الميزات.

كانت هذه هي ميزات مجال التردد ، والتي لها تطبيقات في العديد من التجارب العلمية ذات الصلة بالسلاسل الزمنية. ومع ذلك ، حتى الوظائف التجميعية الأبسط للنطاق الزمني مثل الانحراف المعياري لا يمكن دعمها بشكل فعال عن طريق إعادة التشكيل.

على الرغم من أنني لا أعتقد أن هذا صعب التنفيذ بالفعل (على الرغم من أنه سيشمل عددًا من التغييرات في التنفيذ). نحن نستخدم النوافذ الهامشية (IOW ، احسب النافذة وكلما تقدمت ، أسقط النقاط التي تغادر وأضف النقاط التي تكتسبها). لذلك لا يزال يتعين عليك حساب كل شيء ، لكنك لن تخرجه.

يجب أن يكون وجود معلمة "الخطوة" والقدرة على تقليل العمليات الحسابية الفعلية باستخدامها هو الهدف المستقبلي لباندا. إذا كانت معلمة الخطوة ترجع عددًا أقل من النقاط فقط ، فهذا لا يستحق القيام به ، لأنه يمكننا تقسيم الإخراج على أي حال. ربما بالنظر إلى العمل الذي ينطوي عليه القيام بذلك ، قد نوصي فقط بجميع المشاريع التي تحتوي على هذه الاحتياجات لاستخدام Numpy.

Murmuria أنتم مدعوون لتقديم طلب سحب للقيام بذلك. في الواقع ليس بهذه الصعوبة.

بينما أؤيد طلب معلمة step في rolling() ، أود أن أشير إلى أنه من الممكن الحصول على النتيجة المرجوة باستخدام المعلمة base في resample() ، إذا كان حجم الخطوة هو عدد صحيح من حجم النافذة . باستخدام مثالalexlouden :

pandas.concat([
    s.resample('30s', label='left', loffset=pandas.Timedelta(15, unit='s'), base=i).agg(p2p) 
    for i in range(30)
]).sort_index().plot(ax=ax, label='Solution with resample()', legend=True, style='k:')

نحصل على نفس النتيجة (لاحظ أن الخط يمتد بمقدار 30 ثانية على كلا الجانبين):
rolling_with_step_using_resample

هذا لا يزال مضيعة إلى حد ما ، اعتمادًا على نوع التجميع. بالنسبة للحالة الخاصة لحساب الذروة إلى الذروة كما في مثالalexlouden ، يكون p2p_arr() أسرع 200 مرة تقريبًا لأنه يعيد ترتيب السلسلة إلى مصفوفة ثنائية الأبعاد ثم يستخدم مكالمة واحدة إلى max() و min() .

تسمح معلمة الخطوة في التدحرج أيضًا باستخدام هذه الميزة بدون فهرس التاريخ والوقت. هل هناك أي شخص يعمل بالفعل على ذلك؟

alexlouden أعلاه قال هذا:

من الواضح أنه يمكنني الرجوع إلى numpy ، لكن سيكون من الجيد أن يكون هناك مستوى أعلى من واجهة برمجة التطبيقات للقيام بذلك.

هل يمكن لـ alexlouden أو أي شخص آخر يعرف أن يشاركك بعض الأفكار حول كيفية القيام بذلك مع numpy؟ من خلال بحثي حتى الآن ، يبدو أنه ليس من التافه القيام بذلك سواء في numpy. في الواقع ، هناك مشكلة مفتوحة حول هذا الموضوع هنا https://github.com/numpy/numpy/issues/7753

شكرا

مرحبًا tsando - هل الوظيفة rolling_with_step استخدمتها أعلاه لا تعمل من أجلك؟

شكرًا alexlouden ، فقط تحقق من هذه الوظيفة ويبدو أنها لا تزال تعتمد على الباندا (تأخذ سلسلة كمدخل وتستخدم أيضًا فهرس السلسلة). كنت أتساءل ما إذا كان هناك نهج محض بحت في هذا الشأن. في الخيط الذي ذكرته https://github.com/numpy/numpy/issues/7753 ، اقترحوا وظيفة تستخدم خطوات معقدة ، لكن يصعب فهمها وترجمتها إلى مدخلات النافذة والخطوات.

tsando هنا ملف PDF من منشور المدونة الذي قمت بربطه أعلاه - يبدو أن المؤلف قد غير اسم مستخدم Github الخاص به ولم يضع موقعه مرة أخرى. (لقد قمت بتشغيله محليًا فقط لتحويله إلى PDF).

كانت وظيفتي أعلاه هي تحويل مثاله الأخير للعمل مع Pandas - إذا كنت تريد استخدام numpy مباشرةً ، يمكنك فعل شيء مثل هذا: https://gist.github.com/alexlouden/e42f1d96982f7f005e62ebb737dcd987

أتمنى أن يساعدك هذا!

alexlouden شكرا! لقد جربته للتو على مصفوفة من الشكل (13, 1313) لكنها أعطتني هذا الخطأ:

image

"يمكن القيام بذلك ، لكني أرغب في رؤية حالة استخدام حيث يكون هذا مهمًا."

مهما كان المشروع الذي عملت عليه باستخدام الباندا ، فقد فاتني دائمًا هذه الميزة ، فهي مفيدة في كل مرة تحتاج فيها إلى حساب التطبيق مرة واحدة فقط من حين لآخر ولكن لا تزال بحاجة إلى دقة جيدة داخل كل نافذة.

أنا أوافق وأدعم هذه الميزة أيضا

إذا كنت بحاجة إليها في كل مرة تقريبًا عند التعامل مع السلاسل الزمنية ، يمكن أن توفر الميزة تحكمًا أفضل بكثير لإنشاء ميزات السلاسل الزمنية لكل من التصور والتحليل. دعم بقوة هذه الفكرة!

توافق ودعم هذه الميزة أيضا

سيكون هذا مفيدًا جدًا لتقليل وقت الحوسبة مع الحفاظ على دقة نافذة جيدة.

أقدم رموز الحل ، والتي يمكن تعديلها بشكل أكبر وفقًا لهدفك المحدد.

def average_smoothing(signal, kernel_size, stride):
    sample = []
    start = 0
    end = kernel_size
    while end <= len(signal):
        start = start + stride
        end = end + stride
        sample.append(np.mean(signal[start:end]))
    return np.array(sample)

أوافق وأدعم هذه الميزة. أرى أنه في حالة توقف الآن.

الحساب ثم الاختزال ليس خيارًا عندما يكون لديك تيرابايت من البيانات.

سيكون مفيدًا جدًا فيما أفعله أيضًا. لدي تيرابايت من البيانات حيث أحتاج إلى إحصائيات مختلفة للنوافذ غير المتداخلة لفهم الظروف المحلية. "الإصلاح" الحالي الخاص بي هو فقط إنشاء منشئ يقوم بتقطيع إطارات البيانات وإحصاءات النتائج. سيكون من المفيد جدا الحصول على هذه الميزة.

هذه الميزة ضرورية بالفعل عندما يتعلق الأمر بالسلسلة الزمنية!

موافق ، بالتأكيد أحتاج إلى إضافة هذه الميزة. أحاول القيام بتشغيل ارتباطات النافذة بين أسعار الأسهم وعليك إنشاء وظيفتي الخاصة لذلك

لا أصدق أن هذه الميزة الأساسية ليست موجودة حتى الآن!
متى سيتم حل هذه المشكلة؟
شكرا

للمساهمة في "مزيد من المناقشة":
حالة الاستخدام الخاصة بي هي حساب قيمة دقيقة / قصوى / وسيطة واحدة لكل ساعة لمدة شهر من البيانات بدقة ثانية واحدة. إنها بيانات استخدام الطاقة وهناك قمم لمدة 1-2 ثانية قد أفقدها مع إعادة التشكيل. بخلاف ذلك ، لن تؤدي إعادة التشكيل إلى 5 ثوانٍ / دقيقة واحدة على سبيل المثال إلى تغيير حقيقة أنه لا يزال يتعين علي حساب 4k / 1k windows في اليوم الذي يجب التخلص منه ، بدلاً من مجرد القدرة على حساب 24 نافذة مطلوبة في اليوم .

سيكون من الممكن التغلب على هذا باستخدام groupby aso ولكن يبدو أن هذا ليس بديهيًا ولا سريعًا مثل التنفيذ المتداول (ثانيتان للنوافذ التي يبلغ طولها 2.5 ميل مع الفرز). إنه سريع ومفيد بشكل مثير للإعجاب ، لكننا نحتاج حقًا إلى حجة خطوة للاستفادة الكاملة من قوتها.

ألقيت نظرة على المشكلة. هذا أمر تافه نسبيًا ، ولكن الطريقة التي يتم بها تنفيذ الكود ، من نظرة خاطفة أعتقد أنه سيتطلب من شخص ما العمل يدويًا من خلال تعديل جميع الإجراءات الروتينية. لا أحد منهم يحترم حدود النافذة التي قدمتها فئات المفهرس. إذا فعلوا ذلك ، فسيكون من السهل جدًا حل هذا الطلب وكذلك # 11704. على أي حال ، أعتقد أنه يمكن التحكم فيه لأي شخص يريد قضاء بعض الوقت في تجميل الأشياء. لقد بدأت في العلاقات العامة نصف المخبوزة (من المتوقع أن يتم رفضها ، فقط من أجل MVP) لتوضيح كيف سأعالج المشكلة.

ادارة:

import numpy as np
import pandas as pd

data = pd.Series(
    np.arange(100),
    index=pd.date_range('2020/05/12 12:00:00', '2020/05/12 12:00:10', periods=100))

print('1s rolling window every 2s')
print(data.rolling('1s', step='2s').apply(np.mean))

data.sort_index(ascending=False, inplace=True)

print('1s rolling window every 500ms (and reversed)')
print(data.rolling('1s', step='500ms').apply(np.mean))

عائدات

1s rolling window every 2s
2020-05-12 12:00:00.000000000     4.5
2020-05-12 12:00:02.020202020    24.5
2020-05-12 12:00:04.040404040    44.5
2020-05-12 12:00:06.060606060    64.5
2020-05-12 12:00:08.080808080    84.5
dtype: float64
1s rolling window every 500ms (and reversed)
2020-05-12 12:00:10.000000000    94.5
2020-05-12 12:00:09.494949494    89.5
2020-05-12 12:00:08.989898989    84.5
2020-05-12 12:00:08.484848484    79.5
2020-05-12 12:00:07.979797979    74.5
2020-05-12 12:00:07.474747474    69.5
2020-05-12 12:00:06.969696969    64.5
2020-05-12 12:00:06.464646464    59.5
2020-05-12 12:00:05.959595959    54.5
2020-05-12 12:00:05.454545454    49.5
2020-05-12 12:00:04.949494949    44.5
2020-05-12 12:00:04.444444444    39.5
2020-05-12 12:00:03.939393939    34.5
2020-05-12 12:00:03.434343434    29.5
2020-05-12 12:00:02.929292929    24.5
2020-05-12 12:00:02.424242424    19.5
2020-05-12 12:00:01.919191919    14.5
2020-05-12 12:00:01.414141414     9.5
2020-05-12 12:00:00.909090909     4.5
dtype: float64

للحصول على تفاصيل التنفيذ ، ألق نظرة على العلاقات العامة (أو هنا: https://github.com/anthonytw/pandas/tree/rolling-window-step)

على الرغم من أنني كنت أرغب في قضاء المزيد من الوقت لإنهائه ، إلا أنني للأسف لم يتبق لي شيء لمعالجة العمل الشاق المتمثل في إعادة صياغة جميع وظائف التدوير. توصيتي لأي شخص يريد معالجة هذا الأمر أن يفرض حدود النافذة التي تم إنشاؤها بواسطة فئات المفهرس وتوحيد الدوال _ * _ الثابتة / المتغيرة. مع حدود البداية والنهاية ، لا أرى أي سبب يجب أن يكونا مختلفين ، إلا إذا كان لديك وظيفة تقوم بشيء خاص مع بيانات عينات غير موحدة (في هذه الحالة ، ستكون هذه الوظيفة المحددة أكثر قدرة على التعامل مع الفروق الدقيقة ، لذلك ربما ضع علامة أو شيء من هذا القبيل).

هل سيعمل هذا أيضًا مع نافذة مخصصة باستخدام نهج get_window_bounds() ؟

مرحبًا ، أنا أيضًا الاقتراح من فضلك. ستكون هذه ميزة مفيدة حقًا.

إذا كنت تستخدم وظائف "قياسية" ، فهذه دوال متجهة ، وبالتالي v سريعًا ( ts.rolling(5).max().dropna()[::2] ).

IIUC يأتي التوفير هنا من تطبيق الوظيفة فقط في جزء صغير من الوقت (على سبيل المثال كل قيمة نونية). ولكن هل هناك حالة يحدث فيها ذلك فرقًا عمليًا؟

لدي مثل هذا المثال هنا: https://stackoverflow.com/questions/63729190/pandas-resample-daily-data-to-annual-data-with-overlap-and-offset

كل N سيكون كل 365. يتغيّر حجم النافذة على مدى عمر البرنامج ولا يمكن ضمان أن تكون الخطوة جزءًا صحيحًا من حجم النافذة.

أحتاج أساسًا إلى حجم نافذة محدد يتدرج حسب "عدد أيام السنة التي تبحث فيها" وهو أمر مستحيل مع كل حل وجدته لهذه المشكلة حتى الآن.

لدي أيضًا حاجة مماثلة في السياق التالي (مقتبس من حاجة حقيقية ومهنية):

  • لدي إطار بيانات زمني مع عمود طابع زمني وعمود قيم ، والذي يمثل أحداثًا غير منتظمة. مثل الطابع الزمني عندما مر كلب أسفل نافذتي وعدد الثواني التي استغرقتها لتمريرها. يمكنني أن أحصل على 6 أحداث في يوم معين وبعد ذلك لا يوجد أي حدث على الإطلاق في اليومين المقبلين
  • أرغب في حساب مقياس (دعنا نقول متوسط ​​الوقت الذي تقضيه الكلاب أمام نافذتي) مع نافذة متدرجة لمدة 365 يومًا ، والتي من شأنها أن تتدحرج كل 30 يومًا

بقدر ما أفهم ، تسمح لي dataframe.rolling () API بتحديد مدة 365 يومًا ، ولكن ليس الحاجة إلى تخطي 30 يومًا من القيم (وهو عدد غير ثابت من الصفوف) لحساب المتوسط ​​التالي على حساب آخر اختيار 365 يومًا من القيم.

من الواضح أن إطار البيانات الناتج الذي أتوقعه سيكون له عدد صفوف أصغر (بكثير) من إطار بيانات "أحداث الكلاب" الأولي.

فقط لتوضيح هذا الطلب بمثال بسيط.

إذا كانت لدينا هذه السلسلة:

In [1]: s = pd.Series(range(5))

In [2]: s
Out[2]:
0    0
1    1
2    2
3    3
4    4
dtype: int64

ولدينا نافذة بحجم 2 وحجم الخطوة 1 . سيتم تقييم هذه النافذة الأولى في الفهرس 0 ، وتخطى النافذة في الفهرس 1 ، قم بتقييم النافذة في الفهرس 2 ، وما إلى ذلك؟

In [3]: s.rolling(2, step=1, min_periods=0).max()

Out[3]:
0    0.0
1    NaN # step over this observation
2    2.0
3    NaN # step over this observation
4    4.0
dtype: float64

وبالمثل إذا كان لدينا هذه السلسلة الزمنية

In [1]: s = pd.Series(range(5), index=pd.DatetimeIndex(['2020-01-01', '2020-01-02', '2020-01-03', '2020-01-06', '2020-01-09']))

In [2]: s
Out[2]:
2020-01-01    0
2020-01-02    1
2020-01-03    2
2020-01-06    3
2020-01-09    4
dtype: int64

ولدينا نافذة بحجم '3D' وحجم الخطوة '3D' . هل ستكون هذه هي النتيجة الصحيحة؟

In [3]: s.rolling('3D', step='3D', min_periods=0).max()

Out[3]:
2020-01-01    0.0       # evaluate this window
2020-01-02    NaN    # step over this observation (2020-01-01 + 3 days > 2020-01-02)
2020-01-03    NaN    # step over this observation (2020-01-01 + 3 days > 2020-01-03)
2020-01-06    3.0      # evaluate this window ("snap back" to this observation)
2020-01-09    4.0      # evaluate this window (2020-01-06 + 3 days = 2020-01-09)
dtype: float64

mroeschke wrt إلى المثال الأول ([3]) ، النتائج ليست ما كنت أتوقعه. أفترض أن هذه نافذة زائدة (على سبيل المثال ، عند الفهرس = 0 ، سيكون الحد الأقصى للعناصر عند -1 و 0 ، لذلك فقط max ([0]) ، ثم يجب أن يتقدم للأمام "1" index ، للفهرس = 0 + الخطوة = 1 ، والحساب التالي سيكون الحد الأقصى ([0،1]) ، ثم الحد الأقصى ([1،2]) ، وما إلى ذلك. الانتقال من الفهرس = 0 إلى الفهرس = 0 + 2 = 2 (تخطي الفهرس 1) ، والاستمرار على هذا النحو. في هذه الحالة يكون الأمر صحيحًا تقريبًا ، ولكن يجب ألا يكون هناك أرقام NaN. في حين أنه قد يكون ضعف الحجم "فقط" في هذا الحالة ، في حالات أخرى ، تكون كبيرة. على سبيل المثال ، لدي ما يقرب من ساعة من بيانات تخطيط القلب 500 هرتز لمريض ، وهذا يعني 1.8 مليون عينة. إذا كنت أرغب في متوسط ​​متحرك لمدة 5 دقائق كل دقيقتين ، فسيكون ذلك مجموعة من 1.8 مليون عنصر مع 30 عملية حسابية صالحة وأقل بقليل من 1.8 مليون NaN. :-)

بالنسبة للفهرسة ، فإن حجم الخطوة = 1 هو السلوك الحالي ، أي حساب الميزة محل الاهتمام باستخدام البيانات الموجودة في النافذة ، وتحويل النافذة بمقدار واحد ، ثم كرر. في هذا المثال ، أرغب في حساب الميزة ذات الأهمية باستخدام البيانات الموجودة في النافذة ، ثم الانتقال بمقدار 60 ألف مؤشر ، ثم كرر ذلك.

تصريحات مماثلة في ذلك الوقت. في هذه الحالة ، قد يكون هناك بعض الخلاف حول الطريقة الصحيحة لتنفيذ هذا النوع من النوافذ ، ولكن في رأيي ، فإن الطريقة "الأفضل" (TM) هي البدء من الوقت t0 ، والعثور على جميع العناصر في النطاق (t0-window ، t0] ، احسب الميزة ، ثم تحرك حسب حجم الخطوة. تخلص من أي نوافذ بها أقل من الحد الأدنى لعدد العناصر (يمكن تكوينها ، افتراضيًا إلى 1). هذا المثال مخصص لنافذة لاحقة ، ولكن يمكنك تعديل لتناسب أي تكوين للنافذة. وهذا له عيب هو إضاعة الوقت في فجوات كبيرة ، ولكن يمكن التعامل مع الفجوات بذكاء وحتى إذا قمت بحساب الطريقة الساذجة (لأنك كسول مثلي) لم أر هذه المسألة في الممارسة حتى الآن ، لأن الفجوات عادة ليست كبيرة بما يكفي لتكون مهمة في البيانات الحقيقية.

ربما هذا أوضح؟ ألق نظرة على المثال الخاص بي + الكود أعلاه ، فقد يفسر ذلك بشكل أفضل.

شكرا للتوضيحanthonytw. في الواقع ، يبدو أنني بحاجة إلى تفسير step أنه "خطوة إلى نقطة".

بالنسبة إلى NaNs ، أفهم المشاعر لإسقاط NaNs في نتيجة الإخراج تلقائيًا ، ولكن كما هو مذكور في https://github.com/pandas-dev/pandas/issues/15354#issuecomment -278676420 بواسطة jreback ، هناك اعتبار تناسق API بحيث يكون للمخرجات نفس طول المدخلات. قد يكون هناك مستخدم يرغب في الاحتفاظ بـ NaN أيضًا (ربما؟) ، وسيظل dropna متاحًا بعد العملية rolling(..., step=...).func() .

mroeschke أعتقد أنه ينبغي إجراء استثناءات. طالما أنك وضعت ملاحظة صريحة في الوثائق ، ولم يكن السلوك افتراضيًا ، فلن يتأثر أحد سلبًا بعدم إرجاع متجه مليء بالخردة. الحفاظ على NaNs يهزم نصف الغرض. أحد الأهداف هو الحد من عدد المرات التي نجري فيها عملية حسابية باهظة الثمن. الهدف الآخر هو تقليل مجموعة الميزات إلى شيء يمكن التحكم فيه. هذا المثال الذي قدمته لكم هو مثال حقيقي ، وليس بالقدر نفسه من البيانات التي يجب معالجتها في تطبيق مراقبة المريض. هل من الضروري حقًا تخصيص 60000x المساحة اللازمة ، ثم البحث في المصفوفة لحذف NaNs؟ لكل ميزة نريد حسابها؟

لاحظ أن عملية حسابية واحدة قد تنتج مصفوفة من القيم. ماذا أريد أن أفعل مع شكل موجة ECG؟ حسنًا ، احسب طيف الطاقة بالطبع! لذلك أحتاج إلى تخصيص مساحة كافية لمتجه PSD كامل (150000 عنصر) 1.8 مليون مرة (2 تيرابايت من البيانات) ثم التصفية للحصول على القطع التي تهمني (34 ميجا بايت). لجميع هذه السلسلة. لجميع المرضى. أعتقد أنني بحاجة لشراء المزيد من ذاكرة الوصول العشوائي!

من الجدير بالذكر أيضًا أن NaN ، بالنسبة لبعض الميزات ، قد يكون ناتجًا ذا مغزى. في هذه الحالة ، لم يعد بإمكاني التمييز بين NaN ذي المعنى و NaNs غير المرغوب فيه الذي يحشو البيانات.

على الرغم من أنني أتفهم الرغبة في الحفاظ على واجهة برمجة التطبيقات ، فهذه ليست ميزة من شأنها كسر أي كود موجود (لأنها ميزة جديدة لم تكن موجودة من قبل) ، وبالنظر إلى الوظيفة ، لا يوجد سبب يتوقع أي شخص أن ينتج عنها إخراج من نفس الحجم. وحتى لو فعلوا ذلك ، فستكون ملاحظة في الوثائق لحجم الخطوة كافية. تفوق العيوب بكثير أي فائدة من وجود واجهة برمجة تطبيقات "متسقة" (لميزة لم تكن موجودة من قبل ، ضع في اعتبارك). سيؤدي عدم المضي في هذه الطريقة إلى تعطيل الميزة ، يكاد لا يستحق التنفيذ في هذه الحالة (من واقع خبرتي ، فإن تكلفة المساحة هي العامل الأكبر دائمًا).

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات