ฉันมีเวกเตอร์เช่น: 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
จะดีกว่าเนื่องจากทำทุกอย่างในการดำเนินการเดียวและอ้างอิงเวกเตอร์ที่แก้ไขเพียงครั้งเดียว