ฉันเรียนรู้ R เร็ว ๆ นี้และสับสนโดยทั้งสองฟังก์ชั่นและlapply
do.call
ดูเหมือนว่าพวกเขาจะคล้ายกับmap
ฟังก์ชั่นใน Lisp แต่ทำไมมีสองฟังก์ชั่นที่มีชื่อต่างกัน? ทำไม R ไม่ใช้ฟังก์ชั่นที่เรียกว่าmap
?
ฉันเรียนรู้ R เร็ว ๆ นี้และสับสนโดยทั้งสองฟังก์ชั่นและlapply
do.call
ดูเหมือนว่าพวกเขาจะคล้ายกับmap
ฟังก์ชั่นใน Lisp แต่ทำไมมีสองฟังก์ชั่นที่มีชื่อต่างกัน? ทำไม R ไม่ใช้ฟังก์ชั่นที่เรียกว่าmap
?
คำตอบ:
มีฟังก์ชั่นที่เรียกMap
ว่าอาจคล้ายกับแผนที่ในภาษาอื่น ๆ :
lapply
ส่งคืนรายการความยาวเดียวกันกับ X แต่ละองค์ประกอบซึ่งเป็นผลลัพธ์ของการใช้ความสนุกกับองค์ประกอบที่สอดคล้องกันของ X
do.call
สร้างและดำเนินการเรียกใช้ฟังก์ชั่นจากชื่อหรือฟังก์ชั่นและรายการของข้อโต้แย้งที่จะส่งผ่านไปยังมัน
Map
ใช้ฟังก์ชันกับองค์ประกอบที่สอดคล้องกันของเวกเตอร์ที่ให้ ... Map
เป็นตัวห่อหุ้มอย่างง่ายmapply
ซึ่งไม่ได้พยายามทำให้ผลลัพธ์ง่ายขึ้นคล้ายกับ mapcar ทั่วไปของ Lisp (โดยมีข้อโต้แย้งที่ถูกนำมารีไซเคิล) เวอร์ชันในอนาคตอาจอนุญาตการควบคุมประเภทผลลัพธ์บางอย่าง
Map
เป็นเสื้อคลุมรอบ ๆ mapply
lapply
เป็นกรณีพิเศษของ mapply
Map
และlapply
จะคล้ายกันในหลายกรณีตัวอย่างเช่นนี่คือlapply
:
lapply(iris, class)
$Sepal.Length
[1] "numeric"
$Sepal.Width
[1] "numeric"
$Petal.Length
[1] "numeric"
$Petal.Width
[1] "numeric"
$Species
[1] "factor"
และเช่นเดียวกันโดยใช้Map
:
Map(class, iris)
$Sepal.Length
[1] "numeric"
$Sepal.Width
[1] "numeric"
$Petal.Length
[1] "numeric"
$Petal.Width
[1] "numeric"
$Species
[1] "factor"
do.call
ใช้ฟังก์ชั่นเป็นอินพุตและกระจายข้อโต้แย้งอื่น ๆ ไปยังฟังก์ชั่น มันถูกใช้กันอย่างแพร่หลายตัวอย่างเช่นการรวบรวมรายการเป็นโครงสร้างที่เรียบง่าย (มักจะมีrbind
หรือcbind
)
ตัวอย่างเช่น:
x <- lapply(iris, class)
do.call(c, x)
Sepal.Length Sepal.Width Petal.Length Petal.Width Species
"numeric" "numeric" "numeric" "numeric" "factor"
do.call(cbind, x)
รุ่นปัจจุบันให้ฉันError in do.call(c, x) : 'what' must be a function or character string
...
cbind()
นั้นแตกต่างจากฟังก์ชั่นc()
และแม้ว่าจะใช้งานได้ แต่ก็ให้ผลลัพธ์ที่แตกต่าง
lapply
ใช้ฟังก์ชั่นมากกว่ารายการdo.call
เรียกใช้ฟังก์ชั่นที่มีรายการข้อโต้แย้ง ดูเหมือนว่าจะแตกต่างสำหรับฉัน ...
ในการให้ตัวอย่างกับรายการ:
X <- list(1:3,4:6,7:9)
ด้วย lapply คุณจะได้รับค่าเฉลี่ยของทุกองค์ประกอบในรายการดังนี้:
> lapply(X,mean)
[[1]]
[1] 2
[[2]]
[1] 5
[[3]]
[1] 8
do.call
ให้ข้อผิดพลาดตามที่คาดว่าอาร์กิวเมนต์ "trim" จะเป็น 1
ในทางกลับกันการrbind
โยงข้อโต้แย้งทั้งหมด ดังนั้นในการผูก X rowwise คุณต้อง:
> do.call(rbind,X)
[,1] [,2] [,3]
[1,] 1 2 3
[2,] 4 5 6
[3,] 7 8 9
หากคุณต้องการใช้lapply
R จะใช้rbind
กับทุกองค์ประกอบของรายการโดยให้เรื่องไร้สาระนี้แก่คุณ:
> lapply(X,rbind)
[[1]]
[,1] [,2] [,3]
[1,] 1 2 3
[[2]]
[,1] [,2] [,3]
[1,] 4 5 6
[[3]]
[,1] [,2] [,3]
[1,] 7 8 9
ในการมีบางสิ่งบางอย่างเช่นแผนที่คุณต้องการ?mapply
ซึ่งเป็นสิ่งที่แตกต่างกันโดยสิ้นเชิง วิธีรับเช่นค่าเฉลี่ยของทุกองค์ประกอบใน X แต่ด้วยการตัดแต่งที่แตกต่างกันคุณสามารถใช้:
> mapply(mean,X,trim=c(0,0.5,0.1))
[1] 2 5 8
lapply
คือการที่คล้ายกันmap
, do.call
ไม่ได้ lapply
ใช้ฟังก์ชันกับองค์ประกอบทั้งหมดของรายการdo.call
เรียกใช้ฟังก์ชันที่อาร์กิวเมนต์ของฟังก์ชันทั้งหมดอยู่ในรายการ ดังนั้นสำหรับn
รายการองค์ประกอบlapply
มีn
การเรียกใช้ฟังก์ชันและdo.call
มีการเรียกใช้ฟังก์ชันเพียงครั้งเดียว ดังนั้นค่อนข้างแตกต่างจากdo.call
lapply
หวังว่านี่จะช่วยชี้แจงปัญหาของคุณ
ตัวอย่างรหัส:
do.call(sum, list(c(1, 2, 4, 1, 2), na.rm = TRUE))
และ:
lapply(c(1, 2, 4, 1, 2), function(x) x + 1)
ด้วยคำพูดที่ง่ายที่สุด:
lapply ()ใช้ฟังก์ชันที่กำหนดสำหรับแต่ละองค์ประกอบในรายการดังนั้นจะมีการเรียกใช้ฟังก์ชันหลายอย่าง
do.call ()ใช้ฟังก์ชั่นที่กำหนดให้กับรายการโดยรวมดังนั้นจึงมีการเรียกใช้ฟังก์ชั่นเดียวเท่านั้น
วิธีที่ดีที่สุดในการเรียนรู้คือเล่นกับตัวอย่างฟังก์ชั่นในเอกสาร R
lapply()
เป็นฟังก์ชั่นคล้ายแผนที่ do.call()
แตกต่างกัน มันถูกใช้สำหรับการส่งผ่านข้อโต้แย้งไปยังฟังก์ชั่นในรูปแบบรายการแทนที่จะให้พวกเขาระบุ ตัวอย่างเช่น
> do.call("+",list(4,5))
[1] 9
แม้ว่าจะมีคำตอบมากมาย แต่นี่คือตัวอย่างของฉันสำหรับการอ้างอิง สมมติว่าเรามีรายการข้อมูลดังนี้:
L=list(c(1,2,3), c(4,5,6))
ฟังก์ชันส่งคืนรายการอย่าง lapply
lapply(L, sum)
ด้านบนหมายถึงสิ่งที่ต้องการด้านล่าง
list( sum( L[[1]]) , sum( L[[2]]))
ตอนนี้ให้เราทำสิ่งเดียวกันสำหรับ do.call
do.call(sum, L)
มันหมายถึง
sum( L[[1]], L[[2]])
ในตัวอย่างของเรามันจะคืนค่า 21 ในระยะสั้น lapply ส่งคืนรายการเสมอในขณะที่ชนิดส่งคืนของ do.call ขึ้นอยู่กับฟังก์ชันที่ถูกเรียกใช้
ความแตกต่างระหว่างทั้งสองคือ:
lapply(1:n,function,parameters)
=> สิ่งนี้จะส่ง 1, พารามิเตอร์ของฟังก์ชั่น => สิ่งนี้จะส่ง 2, พารามิเตอร์ของฟังก์ชันและอื่น ๆ
do.call
เพียงแค่ส่ง 1 … n เป็นเวกเตอร์และพารามิเตอร์ไปยังฟังก์ชัน
ดังนั้นในการสมัครคุณมีการเรียกใช้ฟังก์ชัน n ใน do.call คุณมีเพียงครั้งเดียว
do.call
เกือบจะเหมือนกับapply
ใน Lisp