ใน R วิธีใดที่มีประสิทธิภาพมากที่สุดในการนับจำนวนTRUE
ค่าในเวกเตอร์เชิงตรรกะ? ฉันนึกได้สองวิธี:
z <- sample(c(TRUE, FALSE), 1000, rep = TRUE)
sum(z)
# [1] 498
table(z)["TRUE"]
# TRUE
# 498
คุณชอบอันไหน? มีอะไรที่ดีกว่านี้อีกไหม
ใน R วิธีใดที่มีประสิทธิภาพมากที่สุดในการนับจำนวนTRUE
ค่าในเวกเตอร์เชิงตรรกะ? ฉันนึกได้สองวิธี:
z <- sample(c(TRUE, FALSE), 1000, rep = TRUE)
sum(z)
# [1] 498
table(z)["TRUE"]
# TRUE
# 498
คุณชอบอันไหน? มีอะไรที่ดีกว่านี้อีกไหม
คำตอบ:
มีปัญหาบางอย่างเมื่อเวกเตอร์โลจิคัลมีNA
ค่า
ดูตัวอย่าง:
z <- c(TRUE, FALSE, NA)
sum(z) # gives you NA
table(z)["TRUE"] # gives you 1
length(z[z == TRUE]) # f3lix answer, gives you 2 (because NA indexing returns values)
ดังนั้นฉันคิดว่าปลอดภัยที่สุดคือการใช้na.rm = TRUE
:
sum(z, na.rm = TRUE) # best way to count TRUE values
(ซึ่งให้ 1) ฉันคิดว่าtable
วิธีแก้ปัญหานั้นมีประสิทธิภาพน้อยกว่า (ดูที่รหัสtable
ฟังก์ชั่น)
นอกจากนี้คุณควรระวังด้วยวิธีแก้ปัญหา "ตาราง" ในกรณีที่ไม่มีค่า TRUE ในเวกเตอร์เชิงตรรกะ สมมติว่าz <- c(NA, FALSE, NA)
หรือเพียงz <- c(FALSE, FALSE)
แล้วtable(z)["TRUE"]
จะช่วยให้คุณNA
ทั้งสองกรณี
sum(z, na.rm = TRUE)
ตัวเลือกอื่นที่ไม่ได้กล่าวถึงคือการใช้which
:
length(which(z))
เพียงเพื่อให้บริบทบางอย่างเกี่ยวกับ "ซึ่งเป็นคำถามที่เร็วกว่า" มันง่ายที่สุดเพียงแค่ทดสอบตัวเอง ฉันทำให้เวกเตอร์มีขนาดใหญ่กว่ามากสำหรับการเปรียบเทียบ:
z <- sample(c(TRUE,FALSE),1000000,rep=TRUE)
system.time(sum(z))
user system elapsed
0.03 0.00 0.03
system.time(length(z[z==TRUE]))
user system elapsed
0.75 0.07 0.83
system.time(length(which(z)))
user system elapsed
1.34 0.28 1.64
system.time(table(z)["TRUE"])
user system elapsed
10.62 0.52 11.19
ดังนั้นการใช้อย่างชัดเจนจึงsum
เป็นวิธีที่ดีที่สุดในกรณีนี้ คุณอาจต้องการตรวจสอบNA
ค่าตามที่ Marek แนะนำ
เพียงเพิ่มบันทึกเกี่ยวกับค่า NA และwhich
ฟังก์ชัน:
> which(c(T, F, NA, NULL, T, F))
[1] 1 4
> which(!c(T, F, NA, NULL, T, F))
[1] 2 5
โปรดทราบว่าสิ่งใดที่จะตรวจสอบเชิงตรรกะTRUE
เท่านั้นดังนั้นจึงไม่สนใจค่าที่ไม่ใช่เชิงตรรกะ
อีกวิธีคือ
> length(z[z==TRUE])
[1] 498
ในขณะที่sum(z)
ดีและสั้นสำหรับฉันlength(z[z==TRUE])
อธิบายตัวเอง แม้ว่าฉันจะคิดว่างานง่าย ๆ แบบนี้มันไม่ได้สร้างความแตกต่าง ...
sum(z)
ถ้ามันเป็นเวกเตอร์ที่มีขนาดใหญ่คุณอาจจะไปกับวิธีที่เร็วที่สุดซึ่งเป็น length(z[z==TRUE])
เป็นเรื่องเกี่ยวกับ 10x ช้าลงและtable(z)[TRUE]
เป็นเรื่องเกี่ยวกับ 200x sum(z)
ช้ากว่า
ข้อสรุปsum(z)
คือพิมพ์และดำเนินการได้เร็วที่สุด
which
เป็นทางเลือกที่ดีโดยเฉพาะอย่างยิ่งเมื่อคุณทำงานกับเมทริกซ์ (ตรวจสอบ?which
และสังเกตarr.ind
ข้อโต้แย้ง) แต่ฉันขอแนะนำให้คุณติดอยู่sum
เพราะการna.rm
โต้แย้งที่สามารถจัดการกับNA
เวกเตอร์เชิงตรรกะ ตัวอย่างเช่น
# create dummy variable
set.seed(100)
x <- round(runif(100, 0, 1))
x <- x == 1
# create NA's
x[seq(1, length(x), 7)] <- NA
หากคุณพิมพ์sum(x)
คุณจะได้รับNA
ผลที่ตามมา แต่ถ้าคุณผ่านna.rm = TRUE
ในsum
การทำงานของคุณจะได้รับผลที่คุณต้องการ
> sum(x)
[1] NA
> sum(x, na.rm=TRUE)
[1] 43
คำถามของคุณเกี่ยวกับทฤษฎีอย่างเคร่งครัดหรือคุณมีปัญหาในทางปฏิบัติเกี่ยวกับเวกเตอร์เชิงตรรกะ
อีกทางเลือกหนึ่งคือการใช้ฟังก์ชั่นการสรุป มันให้ข้อมูลสรุปของ Ts, Fs และ NAs
> summary(hival)
Mode FALSE TRUE NA's
logical 4367 53 2076
>
summary(hival)["TRUE"]
:;
ฉันได้ทำสิ่งที่คล้ายกันไม่กี่สัปดาห์ที่ผ่านมา นี่เป็นวิธีแก้ปัญหาที่เป็นไปได้มันเขียนมาตั้งแต่ต้นดังนั้นจึงเป็นรุ่นเบต้าหรืออะไรทำนองนั้น ฉันจะพยายามปรับปรุงโดยลบลูปออกจากรหัส ...
แนวคิดหลักคือการเขียนฟังก์ชั่นที่จะรับอาร์กิวเมนต์ 2 (หรือ 3) อันแรกคือdata.frame
ข้อมูลที่เก็บรวบรวมจากแบบสอบถามและอันที่สองเป็นเวกเตอร์ตัวเลขที่มีคำตอบที่ถูกต้อง (ใช้ได้กับแบบสอบถามตัวเลือกเดียวเท่านั้น) หรือคุณสามารถเพิ่มอาร์กิวเมนต์ที่สามที่จะส่งคืนเวกเตอร์ตัวเลขด้วยคะแนนสุดท้ายหรือ data.frame พร้อมคะแนนที่ฝังไว้
fscore <- function(x, sol, output = 'numeric') {
if (ncol(x) != length(sol)) {
stop('Number of items differs from length of correct answers!')
} else {
inc <- matrix(ncol=ncol(x), nrow=nrow(x))
for (i in 1:ncol(x)) {
inc[,i] <- x[,i] == sol[i]
}
if (output == 'numeric') {
res <- rowSums(inc)
} else if (output == 'data.frame') {
res <- data.frame(x, result = rowSums(inc))
} else {
stop('Type not supported!')
}
}
return(res)
}
ฉันจะลองทำสิ่งนี้อย่างสง่างามด้วยฟังก์ชั่น * ply โปรดสังเกตว่าฉันไม่ได้na.rm
โต้แย้ง ... จะทำเช่นนั้น
# create dummy data frame - values from 1 to 5
set.seed(100)
d <- as.data.frame(matrix(round(runif(200,1,5)), 10))
# create solution vector
sol <- round(runif(20, 1, 5))
ตอนนี้ใช้ฟังก์ชั่น:
> fscore(d, sol)
[1] 6 4 2 4 4 3 3 6 2 6
หากคุณส่งผ่าน data.frame อาร์กิวเมนต์มันจะส่งคืน data.frame ที่ถูกแก้ไข ฉันจะพยายามแก้ไขสิ่งนี้ ... หวังว่ามันจะช่วยได้!
rowSums(t(t(d)==sol), na.rm=TRUE)
หนึ่งซับ: เวกเตอร์รีไซเคิล R สำหรับการเปรียบเทียบ หากd
เมทริกซ์ของคุณมีตัวพิมพ์เล็กและตัวใหญ่ในคอลัมน์ก็จะทำให้มันง่ายrowSums(d==sol, na.rm=TRUE)
ขึ้น
ฉันเพิ่งมีปัญหาเฉพาะที่ฉันต้องนับจำนวนงบจริงจากเวกเตอร์เชิงตรรกะและสิ่งนี้ทำงานได้ดีที่สุดสำหรับฉัน ...
length(grep(TRUE, (gene.rep.matrix[i,1:6] > 1))) > 5
ดังนั้นนี่จะใช้ชุดย่อยของวัตถุ gene.rep.matrix และใช้การทดสอบแบบลอจิคัลส่งคืนเวกเตอร์โลจิคัล เวกเตอร์นี้ถูกใส่เป็นอาร์กิวเมนต์สำหรับ grep ซึ่งส่งคืนตำแหน่งของรายการ TRUE ใด ๆ จากนั้นความยาวจะคำนวณจำนวน grep ที่พบรายการดังนั้นจึงให้จำนวนรายการ TRUE
นอกจากนี้ยังมีแพ็คเกจที่เรียกbit
ว่าออกแบบมาโดยเฉพาะสำหรับการดำเนินการบูลีนอย่างรวดเร็ว มันมีประโยชน์อย่างยิ่งถ้าคุณมีเวกเตอร์ขนาดใหญ่หรือต้องทำการบูลีนหลายครั้ง
z <- sample(c(TRUE, FALSE), 1e8, rep = TRUE)
system.time({
sum(z) # 0.170s
})
system.time({
bit::sum.bit(z) # 0.021s, ~10x improvement in speed
})
table(c(FALSE))["TRUE"]
ให้ NA ไม่ใช่ 0