قم بتطبيق وظيفة على كل صف من المصفوفة أو إطار بيانات

StackOverflow https://stackoverflow.com/questions/4236368

سؤال

لنفترض أن لديّ مصفوفة 2 ودالة تأخذ مستنقعًا كأحد الحجج. أرغب في تطبيق الوظيفة على كل صف من المصفوفة والحصول على N-Vector. كيف تفعل هذا في ص؟

على سبيل المثال ، أود حساب كثافة التوزيع العادي القياسي ثنائي الأبعاد على ثلاث نقاط:

bivariate.density(x = c(0, 0), mu = c(0, 0), sigma = c(1, 1), rho = 0){
    exp(-1/(2*(1-rho^2))*(x[1]^2/sigma[1]^2+x[2]^2/sigma[2]^2-2*rho*x[1]*x[2]/(sigma[1]*sigma[2]))) * 1/(2*pi*sigma[1]*sigma[2]*sqrt(1-rho^2))
}

out <- rbind(c(1, 2), c(3, 4), c(5, 6))

كيفية تطبيق الوظيفة على كل صف من out?

كيفية تمرير القيم للوسائط الأخرى إلى جانب النقاط إلى الوظيفة بالطريقة التي تحددها؟

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

المحلول

يمكنك ببساطة استخدام apply() وظيفة:

R> M <- matrix(1:6, nrow=3, byrow=TRUE)
R> M
     [,1] [,2]
[1,]    1    2
[2,]    3    4
[3,]    5    6
R> apply(M, 1, function(x) 2*x[1]+x[2])
[1]  4 10 16
R> 

هذا يأخذ مصفوفة ويطبق وظيفة (سخيفة) على كل صف. تقوم بتمرير حجج إضافية إلى الوظيفة في الحجج الرابعة والخامسة ... apply().

نصائح أخرى

في حال كنت ترغب في تطبيق وظائف مشتركة مثل SUM أو الوسط ، يجب استخدامك rowSums أو rowMeans لأنها أسرع من apply(data, 1, sum) مقاربة. خلاف ذلك ، التمسك مع apply(data, 1, fun). يمكنك تمرير حجج إضافية بعد حجة ممتعة (كما اقترح ديرك بالفعل):

set.seed(1)
m <- matrix(round(runif(20, 1, 5)), ncol=4)
diag(m) <- NA
m
     [,1] [,2] [,3] [,4]
[1,]   NA    5    2    3
[2,]    2   NA    2    4
[3,]    3    4   NA    5
[4,]    5    4    3   NA
[5,]    2    1    4    4

ثم يمكنك أن تفعل شيئًا كهذا:

apply(m, 1, quantile, probs=c(.25,.5, .75), na.rm=TRUE)
    [,1] [,2] [,3] [,4] [,5]
25%  2.5    2  3.5  3.5 1.75
50%  3.0    2  4.0  4.0 3.00
75%  4.0    3  4.5  4.5 4.00

فيما يلي مثال قصير على تطبيق وظيفة على كل صف من المصفوفة. (هنا ، تعمل الوظيفة المطبقة على تطبيع كل صف إلى 1.)

ملحوظة: النتيجة من apply() كان لابد نقل استخدام t() للحصول على نفس التصميم مثل مصفوفة الإدخال A.

A <- matrix(c(
  0, 1, 1, 2,
  0, 0, 1, 3,
  0, 0, 1, 3
), nrow = 3, byrow = TRUE)

t(apply(A, 1, function(x) x / sum(x) ))

نتيجة:

     [,1] [,2] [,3] [,4]
[1,]    0 0.25 0.25 0.50
[2,]    0 0.00 0.25 0.75
[3,]    0 0.00 0.25 0.75

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

bvnormdens <- function(x=c(0,0),mu=c(0,0), sigma=c(1,1), rho=0){
     exp(-1/(2*(1-rho^2))*(x[1]^2/sigma[1]^2+
                           x[2]^2/sigma[2]^2-
                           2*rho*x[1]*x[2]/(sigma[1]*sigma[2]))) * 
     1/(2*pi*sigma[1]*sigma[2]*sqrt(1-rho^2))
     }
 out=rbind(c(1,2),c(3,4),c(5,6));

 bvout<-matrix(NA, ncol=1, nrow=3)
 bvout[] <-apply(out, 1, bvnormdens)
 bvout
             [,1]
[1,] 1.306423e-02
[2,] 5.931153e-07
[3,] 9.033134e-15

إذا كنت ترغب في استخدام غير المعلمات الافتراضية الخاصة بك ، فيجب أن تتضمن المكالمة وسيطات مسماة بعد الوظيفة:

bvout[] <-apply(out, 1, FUN=bvnormdens, mu=c(-1,1), rho=0.6)

يمكن استخدام () أيضًا في المصفوفات ذات الأبعاد العليا ويمكن أن تكون حجة الهامش متجهًا بالإضافة إلى عدد صحيح واحد.

تطبيق هل المهمة بشكل جيد ، ولكن بطيئة جدا. باستخدام Sapply و Vapply يمكن أن يكون مفيدًا. يمكن أن يكون Dplyr's Rowwise مفيدًا أيضًا ، دعنا نرى مثالًا على كيفية القيام بمنتج حكيمة لأي إطار بيانات.

a = data.frame(t(iris[1:10,1:3]))
vapply(a, prod, 0)
sapply(a, prod)

لاحظ أن التعيين إلى متغير قبل استخدام vapply/ sapply/ تطبيق هو ممارسة جيدة لأنها تقلل من الوقت كثيرًا. لنرى نتائج Microbenchmark

a = data.frame(t(iris[1:10,1:3]))
b = iris[1:10,1:3]
microbenchmark::microbenchmark(
    apply(b, 1 , prod),
    vapply(a, prod, 0),
    sapply(a, prod) , 
    apply(iris[1:10,1:3], 1 , prod),
    vapply(data.frame(t(iris[1:10,1:3])), prod, 0),
    sapply(data.frame(t(iris[1:10,1:3])), prod) ,
    b %>%  rowwise() %>%
        summarise(p = prod(Sepal.Length,Sepal.Width,Petal.Length))
)

إلقاء نظرة دقيقة على كيفية استخدام T ()

نهج آخر إذا كنت ترغب في استخدام جزء متفاوت من مجموعة البيانات بدلاً من قيمة واحدة هو الاستخدام rollapply(data, width, FUN, ...). يتيح لك استخدام ناقل العروض تطبيق وظيفة على نافذة متفاوتة من مجموعة البيانات. لقد استخدمت هذا لإنشاء روتين تصفية تكيفي ، على الرغم من أنه ليس فعالًا للغاية.

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