سؤال

أحاول استخدام R لحساب المتوسط ​​المتحرك عبر سلسلة من القيم في المصفوفة.بالرغم من ذلك، لم يكن البحث العادي في القائمة البريدية لـ R مفيدًا جدًا.لا يبدو أن هناك وظيفة مدمجة في R سوف يسمح لي بحساب المتوسطات المتحركة.هل توفر أي حزم واحدة؟أم يجب أن أكتب بنفسي؟

هل كانت مفيدة؟

المحلول

نصائح أخرى

أو يمكنك ببساطة حسابه باستخدام الفلتر، وإليك الوظيفة التي أستخدمها:

ma <- function(x, n = 5){filter(x, rep(1 / n, n), sides = 2)}

إذا كنت تستخدم dplyr, ، كن حذرًا في التحديد stats::filter في الوظيفة أعلاه.

استخدام cumsum ينبغي أن تكون كافية وفعالة.على افتراض أن لديك ناقل س وتريد مبلغا جاريا من ن أعداد

cx <- c(0,cumsum(x))
rsum <- (cx[(n+1):length(cx)] - cx[1:(length(cx) - n)]) / n

كما أشار @mzuther في تعليقاته، فإن هذا يفترض عدم وجود NAs في البيانات.للتعامل مع تلك قد يتطلب تقسيم كل نافذة على عدد القيم غير NA.إليك إحدى الطرق للقيام بذلك، من خلال دمج تعليق @Ricardo Cruz:

cx <- c(0, cumsum(ifelse(is.na(x), 0, x)))
cn <- c(0, cumsum(ifelse(is.na(x), 0, 1)))
rx <- cx[(n+1):length(cx)] - cx[1:(length(cx) - n)]
rn <- cn[(n+1):length(cx)] - cn[1:(length(cx) - n)]
rsum <- rx / rn

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

في جدول البيانات 1.12.0 جديد frollmean تمت إضافة وظيفة لحساب المتداول السريع والدقيق يعني التعامل بعناية NA, NaN و +Inf, -Inf قيم.

نظرًا لعدم وجود مثال قابل للتكرار في السؤال، فليس هناك الكثير مما يجب تناوله هنا.

يمكنك العثور على مزيد من المعلومات حول ?frollmean في دليل، متاح أيضا على الانترنت في ?frollmean.

أمثلة من الدليل أدناه:

library(data.table)
d = as.data.table(list(1:6/2, 3:8/4))

# rollmean of single vector and single window
frollmean(d[, V1], 3)

# multiple columns at once
frollmean(d, 3)

# multiple windows at once
frollmean(d[, .(V1)], c(3, 4))

# multiple columns and multiple windows at once
frollmean(d, c(3, 4))

## three above are embarrassingly parallel using openmp

ال caTools تحتوي الحزمة على متوسط ​​دوران سريع جدًا/دقيقة/حد أقصى/SD وعدد قليل من الوظائف الأخرى.لقد عملت فقط مع runmean و runsd وهي الأسرع من أي من الحزم الأخرى المذكورة حتى الآن.

يمكنك استخدام RcppRoll للمتوسطات المتحركة السريعة جدًا المكتوبة بلغة C++.فقط اتصل ب roll_mean وظيفة.يمكن العثور على المستندات هنا.

بخلاف ذلك، يجب أن تؤدي حلقة for (الأبطأ) هذه المهمة:

ma <- function(arr, n=15){
  res = arr
  for(i in n:length(arr)){
    res[i] = mean(arr[(i-n):i])
  }
  res
}

في الحقيقة RcppRoll جيد جدا.

الكود الذي نشرته com.cantdutchthis يجب تصحيحه في السطر الرابع حتى تكون النافذة ثابتة:

ma <- function(arr, n=15){
  res = arr
  for(i in n:length(arr)){
    res[i] = mean(arr[(i-n+1):i])
  }
  res
}

تم تقديم طريقة أخرى للتعامل مع المفقودين هنا.

والطريق الثالث هو التحسين com.cantdutchthis رمز لحساب المتوسطات الجزئية أم لا، كما يلي:

  ma <- function(x, n=2,parcial=TRUE){
  res = x #set the first values

  if (parcial==TRUE){
    for(i in 1:length(x)){
      t<-max(i-n+1,1)
      res[i] = mean(x[t:i])
    }
    res

  }else{
    for(i in 1:length(x)){
      t<-max(i-n+1,1)
      res[i] = mean(x[t:i])
    }
    res[-c(seq(1,n-1,1))] #remove the n-1 first,i.e., res[c(-3,-4,...)]
  }
}

لكي نكمل الرد com.cantdutchthis و رودريجو ريميديو;

moving_fun <- function(x, w, FUN, ...) {
  # x: a double vector
  # w: the length of the window, i.e., the section of the vector selected to apply FUN
  # FUN: a function that takes a vector and return a summarize value, e.g., mean, sum, etc.
  # Given a double type vector apply a FUN over a moving window from left to the right, 
  #    when a window boundary is not a legal section, i.e. lower_bound and i (upper bound) 
  #    are not contained in the length of the vector, return a NA_real_
  if (w < 1) {
    stop("The length of the window 'w' must be greater than 0")
  }
  output <- x
  for (i in 1:length(x)) {
     # plus 1 because the index is inclusive with the upper_bound 'i'
    lower_bound <- i - w + 1
    if (lower_bound < 1) {
      output[i] <- NA_real_
    } else {
      output[i] <- FUN(x[lower_bound:i, ...])
    }
  }
  output
}

# example
v <- seq(1:10)

# compute a MA(2)
moving_fun(v, 2, mean)

# compute moving sum of two periods
moving_fun(v, 2, sum)

على الرغم من كونه بطيئًا بعض الشيء، إلا أنه يمكنك أيضًا استخدام Zoo::rollapply لإجراء العمليات الحسابية على المصفوفات.

reqd_ma <- rollapply(x, FUN = mean, width = n)

حيث x هي مجموعة البيانات، FUN = الوسط هي الدالة؛يمكنك أيضًا تغييره إلى الحد الأدنى والحد الأقصى وSD وما إلى ذلك والعرض هو النافذة المتداول.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top