มีฟังก์ชั่น R สำหรับค้นหาดัชนีขององค์ประกอบในเวกเตอร์หรือไม่?


324

ใน R ฉันมีองค์ประกอบและเวกเตอร์x vฉันต้องการที่จะหาดัชนีแรกขององค์ประกอบในการที่จะมีค่าเท่ากับv xฉันรู้ว่าวิธีหนึ่งในการทำเช่นนี้คือ: which(x == v)[[1]]แต่ดูเหมือนว่าจะไม่มีประสิทธิภาพมากเกินไป มีวิธีโดยตรงมากกว่าที่จะทำหรือไม่

สำหรับคะแนนโบนัสมีฟังก์ชั่นที่ใช้งานxได้หรือไม่ถ้าเป็นเวคเตอร์? นั่นคือมันควรจะกลับเวกเตอร์ของดัชนีระบุตำแหน่งขององค์ประกอบของแต่ละที่ในxv


เนื่องจาก R ได้รับการปรับให้เหมาะกับการทำงานกับเวกเตอร์which(x == v)[[1]]จึงไม่มีประสิทธิภาพมากนัก มันเป็นตัวดำเนินการเปรียบเทียบหนึ่งรายการ ( ==) ที่ใช้กับองค์ประกอบเวกเตอร์ทั้งหมดและอีกหนึ่งส่วนย่อยในดัชนี ( which) แค่นั้นแหละ. ไม่มีสิ่งใดที่ควรเกี่ยวข้องตราบใดที่คุณไม่ได้ใช้งานซ้ำ 10.000 ครั้งในฟังก์ชันนี้ โซลูชันอื่น ๆ เช่นmatchและPositionอาจไม่ส่งคืนข้อมูลได้มากเท่าที่whichควร แต่ไม่จำเป็นต้องมีประสิทธิภาพมากกว่า
BurninLeo

2
คำถามของฉันระบุว่าฉันต้องการฟังก์ชั่นที่มีการทำให้เป็นเวกเตอร์มากกว่า x และwhich(x == v)[[1]]ไม่ใช่
Ryan C. Thompson

คำตอบ:


461

ฟังก์ชั่นใช้matchงานได้บนเวกเตอร์:

x <- sample(1:10)
x
# [1]  4  5  9  3  8  1  6 10  7  2
match(c(4,8),x)
# [1] 1 5

matchส่งกลับเฉพาะการเผชิญหน้าครั้งแรกของการแข่งขันตามที่คุณร้องขอ ส่งคืนตำแหน่งในอาร์กิวเมนต์ที่สองของค่าในอาร์กิวเมนต์แรก

สำหรับการจับคู่หลายรายการ%in%เป็นวิธีที่จะไป:

x <- sample(1:4,10,replace=TRUE)
x
# [1] 3 4 3 3 2 3 1 1 2 2
which(x %in% c(2,4))
# [1]  2  5  9 10

%in%ส่งกลับเวกเตอร์ตรรกะตราบเท่าที่อาร์กิวเมนต์แรกด้วยTRUEถ้าค่าที่สามารถพบได้ในอาร์กิวเมนต์ที่สองและFALSEเป็นอย่างอื่น


ฉันคิดว่าตัวอย่างที่มี c (2,3,3) และ c (1,2,3,4) ที่มีทั้งการจับคู่และ% in% น่าจะเป็นคำแนะนำที่มากขึ้นโดยมีการเปลี่ยนแปลงระหว่างตัวอย่างน้อยลง จับคู่ (c (2,3,3), c (1: 4)) ให้ผลลัพธ์ที่แตกต่างจากที่ (c (2,3,3)% ใน% c (1: 4)) โดยไม่ต้องใช้เวกเตอร์แรกที่ยาวขึ้นและ การเปลี่ยนแปลงมากมายจากตัวอย่างเป็นตัวอย่าง นอกจากนี้ยังเป็นที่น่าสังเกตว่าพวกเขาจัดการกับการแข่งขันที่ไม่แตกต่างกันมาก
จอห์น

1
@ จอห์น: นั่นคือทั้งหมดที่จริง แต่นั่นไม่ใช่สิ่งที่ OP ถาม OP ถามเริ่มจากเวกเตอร์ที่มีความยาวเพื่อค้นหาคู่แรกขององค์ประกอบที่กำหนดในอีกอันหนึ่ง และเพื่อความสมบูรณ์ฉันได้เพิ่มว่าหากคุณสนใจดัชนีทั้งหมดคุณจะต้องใช้ (% ใน%) BTW ไม่มีเหตุผลที่จะลบคำตอบของคุณ มันเป็นข้อมูลที่ถูกต้อง
Joris Meys

1
ฉันคิดว่ามันจะเป็นประโยชน์ในการเน้นว่าลำดับของข้อโต้แย้งในmatchเรื่องต่าง ๆ หากคุณต้องการให้ดัชนีเกิดขึ้นครั้งแรก สำหรับตัวอย่างของคุณmatch(x,c(4,8))ให้ผลลัพธ์ที่แตกต่างซึ่งไม่ชัดเจนในตอนแรก
apitsch

@goldenoslik matchมันจะช่วยถ้าคุณอ่านหน้าความช่วยเหลือของ มันคือทั้งหมดที่อธิบายไว้ที่นั่น แต่ฉันเพิ่มข้อมูลชิ้นนั้น
Joris Meys

ขอบคุณ! โซลูชันนี้ช่วยชีวิตฉันไว้!
Jinhua Wang

26

ฟังก์ชั่นPositionใน funprog {base} ทำงานเช่นกัน จะช่วยให้คุณผ่านฟังก์ชั่นโดยพลการและส่งกลับนัดแรกหรือนัดสุดท้าย

Position(f, x, right = FALSE, nomatch = NA_integer)


10

ข้อควรทราบเล็กน้อยเกี่ยวกับประสิทธิภาพของวิธีการข้างต้น:

 library(microbenchmark)

  microbenchmark(
    which("Feb" == month.abb)[[1]],
    which(month.abb %in% "Feb"))

  Unit: nanoseconds
   min     lq    mean median     uq  max neval
   891  979.0 1098.00   1031 1135.5 3693   100
   1052 1175.5 1339.74   1235 1390.0 7399  100

ดังนั้นสิ่งที่ดีที่สุดคือ

    which("Feb" == month.abb)[[1]]

การวัดประสิทธิภาพของคุณขึ้นอยู่กับเวกเตอร์ที่มีความยาว 12 เท่าดังนั้นจึงไม่มีความหมาย นอกจากนี้ในตัวอย่างของคุณwhich("Feb" == month.abb)ผลตอบแทน2ทำไม[[1]]?
markus

@markus รหัสนี้ซึ่ง ("Feb" == month.abb) [[1]] ส่งคืน "2" และรหัสนี้ซึ่ง (month.abb% ใน% "Feb") ยังส่งคืน "2" ยังไม่ชัดเจนว่าทำไมการใช้เวกเตอร์จึงไม่มีความหมาย
Andrii

1
มันไม่เกี่ยวกับเวกเตอร์ แต่เกี่ยวกับความยาว คุณควรสร้างเวกเตอร์ที่มีความยาวที่เหมาะสมจากนั้นทำเกณฑ์อ้างอิงตามนั้น ข้อความจากตรวจการณ์คำถาม"ฉันรู้ว่าวิธีหนึ่งที่จะทำเช่นนี้คือ: which(x == v)[[1]] , . แต่ที่ดูเหมือนไม่มีประสิทธิภาพมากเกินไป"
markus

-5

R มีการใช้งานตัวดำเนินการ double double เท่ากับ==วิธีการค้นหาดัชนีของเข็มในกองหญ้าแห้งเวกเตอร์ มันให้ผลlogicalเวกเตอร์ที่มีTRUEค่าสำหรับการแข่งขันแต่ละครั้งในกองหญ้า

ตัวอย่าง:

haystack <- c(1, 2, 4, 3, 4)
needle <- 4
indices <- needle == haystack
indices
[1] 3  5
haystack[indices]
[1] 4  4

มันใช้งานได้ถ้าทั้งคู่เป็นเวกเตอร์และสามารถขยายเพื่อใช้หลายเวกเตอร์ได้เช่นกัน


2
==ผู้ประกอบการที่ได้กล่าวถึงแล้วในคำถามของฉันเป็นวิธีแก้ปัญหาที่ไม่มีประสิทธิภาพที่ไม่ได้ทำงานกับเวกเตอร์ของเข็ม
Ryan C. Thompson

"มันใช้งานได้ถ้าทั้งคู่เป็นเวกเตอร์" - อาจขึ้นอยู่กับว่าคุณหมายถึง ... แต่ไม่ใช่ในแง่ที่ว่า OP ต้องการ
แฟรงก์

30
ฉันได้รับFALSE FALSE TRUE FALSE TRUEดัชนีแทนในตัวอย่างนี้
Sashko Lykhenko

6
คุณไม่เคยวิ่งสิ่งนี้ใน R. ==คืนค่าเวกเตอร์เชิงตรรกะไม่ใช่ดัชนี สำหรับสิ่งที่คุณต้องการwhich()ตามที่ฉันอธิบาย 7 ปีที่ผ่านมา
Joris Meys
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.