سؤال

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

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

words <- c("a","quick","brown","fox")

> length(strsplit(words,""))
[1] 4 # The number of words (length of the list)

> length(strsplit(words,"")[[1]])
[1] 1 # The length of the first word only

> sapply(words,function (x) length(strsplit(x,"")[[1]]))
a quick brown   fox 
1     5     5     3 
# Success, but potentially very slow

من الناحية المثالية ، شيء مثل length(strsplit(words,"")[[.]]) أين . يتم تفسيره على أنه الجزء ذي الصلة من متجه الإدخال.

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

المحلول

بشكل عام ، يجب أن تحاول استخدام وظيفة متجهية لتبدأ. استخدام strsplit سيتطلب بشكل متكرر نوعًا من التكرار بعد ذلك (والذي سيكون أبطأ) ، لذا حاول تجنب ذلك إن أمكن. في مثالك ، يجب أن تستخدم nchar في حين أن:

> nchar(words)
[1] 1 5 5 3

بشكل عام ، استفد من حقيقة أن strsplit إرجاع قائمة واستخدام lapply:

> as.numeric(lapply(strsplit(words,""), length))
[1] 1 5 5 3

أو استخدم l*ply وظيفة الأسرة من plyr. على سبيل المثال:

> laply(strsplit(words,""), length)
[1] 1 5 5 3

يحرر:

تكريما ل Bloomsday, ، قررت اختبار أداء هذه الأساليب باستخدام أوليسيس جويس:

joyce <- readLines("http://www.gutenberg.org/files/4300/4300-8.txt")
joyce <- unlist(strsplit(joyce, " "))

الآن بعد أن حصلت على كل الكلمات ، يمكننا القيام بتهمنا:

> # original version
> system.time(print(summary(sapply(joyce, function (x) length(strsplit(x,"")[[1]])))))
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  0.000   3.000   4.000   4.666   6.000  69.000 
   user  system elapsed 
   2.65    0.03    2.73 
> # vectorized function
> system.time(print(summary(nchar(joyce))))
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  0.000   3.000   4.000   4.666   6.000  69.000 
   user  system elapsed 
   0.05    0.00    0.04 
> # with lapply
> system.time(print(summary(as.numeric(lapply(strsplit(joyce,""), length)))))
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  0.000   3.000   4.000   4.666   6.000  69.000 
   user  system elapsed 
    0.8     0.0     0.8 
> # with laply (from plyr)
> system.time(print(summary(laply(strsplit(joyce,""), length))))
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  0.000   3.000   4.000   4.666   6.000  69.000 
   user  system elapsed 
  17.20    0.05   17.30
> # with ldply (from plyr)
> system.time(print(summary(ldply(strsplit(joyce,""), length))))
       V1        
 Min.   : 0.000  
 1st Qu.: 3.000  
 Median : 4.000  
 Mean   : 4.666  
 3rd Qu.: 6.000  
 Max.   :69.000  
   user  system elapsed 
   7.97    0.00    8.03 

وظيفة ناقلات و lapply أسرع بكثير من الأصل sapply إصدار. جميع الحلول تُرجع نفس الإجابة (كما رأينا في الإخراج الموجز).

يبدو أن أحدث إصدار من plyr أسرع (هذا يستخدم نسخة أقدم قليلاً).

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