ฉันมีเวกเตอร์เช่น: a = c(1:10)และฉันต้องการลบหลายค่าเช่น:2, 3, 5
จะลบตัวเลขเหล่านั้น ( ไม่ใช่ตำแหน่งในเวกเตอร์) ในเวกเตอร์ได้อย่างไร?
ในขณะที่ฉันวนเวกเตอร์และทำสิ่งที่ชอบ:
a[!a=NUMBER_TO_REMOVE]
แต่ฉันคิดว่ามีฟังก์ชั่นที่ทำโดยอัตโนมัติ
ฉันมีเวกเตอร์เช่น: a = c(1:10)และฉันต้องการลบหลายค่าเช่น:2, 3, 5
จะลบตัวเลขเหล่านั้น ( ไม่ใช่ตำแหน่งในเวกเตอร์) ในเวกเตอร์ได้อย่างไร?
ในขณะที่ฉันวนเวกเตอร์และทำสิ่งที่ชอบ:
a[!a=NUMBER_TO_REMOVE]
แต่ฉันคิดว่ามีฟังก์ชั่นที่ทำโดยอัตโนมัติ
คำตอบ:
ตัว%in%ดำเนินการจะบอกให้คุณทราบว่าองค์ประกอบใดบ้างที่อยู่ในตัวเลขที่จะลบ:
> a <- sample (1 : 10)
> remove <- c (2, 3, 5)
> a
[1] 10 5 2 7 1 6 3 4 8 9
> a %in% remove
[1] FALSE TRUE TRUE FALSE FALSE FALSE TRUE FALSE FALSE FALSE
> a [! a %in% remove]
[1] 10 7 1 6 4 8 9
โปรดทราบว่าการดำเนินการนี้จะลบสิ่งที่เข้ากันไม่ได้ออกไปอย่างเงียบ ๆ (สิ่งต่างๆเช่นNAหรือInf)เช่นกัน (แม้ว่าจะเก็บค่าที่ซ้ำกันไว้aตราบเท่าที่ไม่มีอยู่ในรายการremove)
หากaสามารถมีสิ่งที่ไม่เหมือนกันได้ แต่removeจะไม่มีเราสามารถใช้matchโดยบอกให้ส่งคืน0สำหรับสิ่งที่ไม่ตรงกันและสิ่งที่เทียบไม่ได้ ( %in%เป็นช็อตคัทสำหรับคอนแวนต์สำหรับmatch):
> a <- c (a, NA, Inf)
> a
[1] 10 5 2 7 1 6 3 4 8 9 NA Inf
> match (a, remove, nomatch = 0L, incomparables = 0L)
[1] 0 3 1 0 0 0 2 0 0 0 0 0
> a [match (a, remove, nomatch = 0L, incomparables = 0L) == 0L]
[1] 10 7 1 6 4 8 9 NA Inf
incomparables = 0ไม่จำเป็นเนื่องจากสิ่งที่ไม่เหมือนกันจะไม่ตรงกันเสมอไป แต่ฉันจะรวมไว้เพื่อประโยชน์ในการอ่าน
นี่คือ btw สิ่งที่setdiffทำภายใน (แต่ไม่มีการuniqueทิ้งรายการที่ซ้ำกันaซึ่งไม่ได้อยู่ในremove)
หากremoveมีสิ่งที่เข้ากันไม่ได้คุณจะต้องตรวจสอบทีละรายการเช่น
if (any (is.na (remove)))
a <- a [! is.na (a)]
(สิ่งนี้ไม่ได้แตกต่างNAจากNaNคู่มือ R แต่อย่างใดเตือนว่าเราไม่ควรพึ่งพาการมีความแตกต่างระหว่างกัน)
สำหรับInf/ -Infคุณจะต้องตรวจสอบทั้งสองsignและis.finite
aที่ไม่ได้อยู่ในremoveนั้นด้วย หากไม่ใช่ปัญหาคุณสามารถใช้setdiffไฟล์. setdiff, btw, ใช้matchซึ่ง%in%เป็นทางลัด
คุณสามารถใช้setdiff.
ป.ร. ให้ไว้
a <- sample(1:10)
remove <- c(2, 3, 5)
แล้วก็
> a
[1] 10 8 9 1 3 4 6 7 2 5
> setdiff(a, remove)
[1] 10 8 9 1 4 6 7
aเป็นผลลัพธ์ของฟังก์ชันอื่นเพื่อให้คุณสามารถทำสิ่งต่างๆในหนึ่งบรรทัดแทนที่จะเป็น 3 และตัวแปร temp
%in%โซลูชันหากเวกเตอร์อินพุตมีรายการที่ซ้ำกัน (ในกรณีนี้setdiffจะส่งคืนเฉพาะชุดที่ไม่ซ้ำกันกล่าวคือไม่มีรายการที่ซ้ำกัน)
fsetdiffของdata.tableแพ็คเกจมีallแฟล็ก(F เริ่มต้น) ที่อนุญาตให้เก็บข้อมูลที่ซ้ำกันในเวกเตอร์อินพุต
คุณสามารถทำได้ดังนี้:
> x<-c(2, 4, 6, 9, 10) # the list
> y<-c(4, 9, 10) # values to be removed
> idx = which(x %in% y ) # Positions of the values of y in x
> idx
[1] 2 4 5
> x = x[-idx] # Remove those values using their position and "-" operator
> x
[1] 2 6
ในไม่ช้า
> x = x[ - which(x %in% y)]
whichที่นี่ โดยพื้นฐานแล้วจะเหมือนกับคำตอบของ @cbeleites
whichส่งกลับดัชนีของค่า TRUE ดังนั้นจึงสามารถใช้เครื่องหมายลบเพื่อบอกว่า "ดัชนีอื่นที่ไม่ใช่ดัชนีเหล่านี้" นอกจากนี้ยังwhichอ่านได้ง่ายกว่าเนื่องจากใกล้เคียงกับภาษาธรรมชาติมากขึ้น
แทน
x <- x[! x %in% c(2,3,5)]
โดยใช้แพ็คเกจpurrrและmagrittrคุณสามารถทำได้:
your_vector %<>% discard(~ .x %in% c(2,3,5))
สิ่งนี้ช่วยให้สามารถsubsetใช้ชื่อเวกเตอร์ได้เพียงครั้งเดียว และคุณสามารถใช้ในท่อ :)
ก่อนอื่นเราสามารถกำหนดตัวดำเนินการใหม่
"%ni%" = Negate( "%in%" )
จากนั้นมันก็เหมือนกับ x ไม่ได้ลบออก
x <- 1:10
remove <- c(2,3,5)
x <- x[ x %ni% remove ]
หรือทำไมต้องไปลบให้ไปโดยตรง
x <- x[ x %ni% c(2,3,5)]
UPDATE:
คำตอบทั้งหมดข้างต้นใช้ไม่ได้กับค่าซ้ำคำตอบของ @ BenBolker โดยใช้เพรดิเคตduplicated()ช่วยแก้ปัญหานี้ได้:
full_vector[!full_vector %in% searched_vector | duplicated(full_vector)]
คำตอบเดิม: ที่นี่ฉันเขียนฟังก์ชันเล็กน้อยสำหรับสิ่งนี้:
exclude_val<-function(full_vector,searched_vector){
found=c()
for(i in full_vector){
if(any(is.element(searched_vector,i))){
searched_vector[(which(searched_vector==i))[1]]=NA
}
else{
found=c(found,i)
}
}
return(found)
}
ดังนั้นขอบอกและfull_vector=c(1,2,3,4,1)searched_vector=c(1,2,3)
exclude_val(full_vector,searched_vector)จะกลับมา (4,1) (4)แต่ข้างต้นคำตอบที่จะกลับมาเพียงแค่
full_vector[!full_vector %in% searched_vector | duplicated(full_vector)]ไง?
full_vector = c(1,1,1,2,3); searched_vector = c(1,1,3);- ที่ผลิตแทนการตอบที่ถูกต้อง1, 1, 2 1, 2
removeif <- function(from, where) { for (i in where) if (i %in% from) {from = from[-match(i, from)]}; from}
q <- c(1,1,2,2,3,3,3,4,4,5,5,7,7)
rm <- q[11]
remove(rm)
q
q[13] = NaN
q
q %in% 7
สิ่งนี้จะตั้งค่า 13 ในเวกเตอร์ไม่ใช่ตัวเลข (NAN) ซึ่งแสดงการลบเท็จ (q [c (11,12,13)]) หากคุณลองทำเช่นนี้คุณจะเห็นว่าฟังก์ชันลบไม่ทำงานกับจำนวนเวกเตอร์ คุณลบเวกเตอร์ทั้งหมด แต่อาจไม่ใช่องค์ประกอบเดียว
นอกจากนี้ยังsubsetมีบางครั้งที่อาจมีประโยชน์:
a <- sample(1:10)
bad <- c(2, 3, 5)
> subset(a, !(a %in% bad))
[1] 9 7 10 6 8 1 4
setdiffจะดีกว่าเนื่องจากทำทุกอย่างในการดำเนินการเดียวและอ้างอิงเวกเตอร์ที่แก้ไขเพียงครั้งเดียว