我正在努力解決與嵌套 for 回圈和條件計算有關的問題。
假設我有一個這樣的資料框:
df = data.frame("a" = c(2, 3, 3, 4),
"b" = c(4, 4, 4, 4),
"c" = c(5, 5, 4, 4),
"d" = c(3, 4, 4, 2))
有了這個df,我想用一個條件比較向量之間的每個元素:如果兩個元素之間的絕對差小于2(所以0和1的差),我想在新創建的向量中賦予1,而兩個元素之間的絕對差 >= 2,我想附加 0。
例如,對于向量“a”和其他向量“b”、“c”、“d”之間的計算,我想要這個結果:0 0 1。第一個 0 是基于 a1 之間的 2 的差異和 b1;第二個0是基于a1和c1之間的差3;1基于a1和d1的差異。因此,我嘗試創建一個嵌套的 for 回圈,以將相同的行程也應用于以下行中的元素。
所以我的第一次試驗是這樣的:
list_all = list(df$a, df$b, df$c, df$d)
v0<-c()
for (i in list_all)
for (j in list_all)
if (i != j) {
if(abs(i-j)<2) {
v0<-c(v0, 1)
} else {
v0<-append(v0, 0)
}} else {
next}
結果是這樣的:
v0
[1] 0 0 1 0 1 1 0 1 0 1 1 0
但似乎只在第一個元素中進行了計算,而不是在后面的元素中進行了計算。
所以我的第二次試驗是這樣的:
list = list(df$b, df$c, df$d)
v1<-c()
for (i in df$a){
for (j in list){
if(abs(i-j)<2) {
v1<-append(v1, 1)
} else {
v1<-append(v1, 0)
}
}
}
v1
v1
[1] 0 0 1 1 0 1 1 0 1 1 1 1
似乎計算是在 df$a 的所有元素和其他元素的第一個元素之間進行的。所以這也不是我需要的。
當我將 df$b 而不是 list 放在嵌套的 for 回圈中時,結果更加混亂。
v2<-c()
for (i in df$a){
for (j in df$b){
if(abs(i-j)<2) {
v2<-append(v2, 1)
} else {
v2<-append(v2, 0)
}
}
}
v2
[1] 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1
似乎沒有在相應的元素之間(在同一行中)進行計算,而是在所有向量之間進行計算,無論位置如何。
誰能告訴我如何解決這個問題?我不明白為什么嵌套的 for 回圈僅適用于第一個元素。
先感謝您。
uj5u.com熱心網友回復:
我不確定我是否理解正確,但是這個怎么樣?
df = data.frame("a" = c(2, 3, 3, 4),
"b" = c(4, 4, 4, 4),
"c" = c(5, 5, 4, 4),
"d" = c(3, 4, 4, 2))
as.vector(apply(df, 1, \(x) ifelse(abs(x[1] - x[2:4]) < 2, 1, 0)))
#> [1] 0 0 1 1 0 1 1 1 1 1 1 0
uj5u.com熱心網友回復:
我認為你讓自己的生活變得不必要地復雜。如果我理解正確的話,你可以做你想做的事,而無需嵌套回圈。
要記住的關鍵是 R默認是矢量化的。這意味著 R 將同時修改向量的所有行。沒有必要回圈。因此,例如,如果a
是一個帶有值的向量1
并且2
我寫a 1
,結果將是一個帶有值2
和的向量3
。
將此邏輯應用于您的案例,您可以撰寫:
df$diffB <- ifelse(abs(df$a-df$b) < 2, 1, 0)
df$diffC <- ifelse(abs(df$a-df$c) < 2, 1, 0)
df$diffD <- ifelse(abs(df$a-df$d) < 2, 1, 0)
df
給予
a b c d diffB diffC diffD
1 2 4 5 3 0 0 1
2 3 4 5 4 1 0 1
3 3 4 4 4 1 1 1
4 4 4 4 2 1 1 0
如果您愿意,您可以撰寫一個回圈來遍歷列,并且 Aron 在他的回答中為您提供了一個選項來執行此操作。
就個人而言,我發現使用 tidyverse 生成的代碼比用基本 R 撰寫的代碼更容易理解。這是因為我可以從左到右閱讀 tidyverse 代碼,而基本 R 代碼(通常)需要從內到外閱讀。Tidyverse 的語法也比基本 R 的語法更一致。
以下是我將如何使用 tidyverse 解決您的問題:
library(tidyverse)
df %>%
mutate(
diffB=ifelse(abs(a-b) < 2, 1, 0),
diffC=ifelse(abs(a-c) < 2, 1, 0),
diffD=ifelse(abs(a-d) < 2, 1, 0)
)
而“列回圈”變為
df %>%
mutate(
across(
c(b, c, d),
~ifelse(abs(a-.x) < 2, 1, 0),
.names="diff{.col}"
)
)
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/470686.html