如何使用跨多列的 if 语句编写 for 循环?
How to write a for loop with if statements across multiple columns?
我的 R 数据框中的一列有一个方向(左、右、L 或 R)。如果此列中的一行是 Left 或 L,我试图将不同列中同一行中的数字转换为负值。这是我到目前为止编写的代码:
for(i in 1:nrow(df)){
if(is.na(df[i,7]==F)){
if(df[i,7]=="Left" | df[i,7]=="L"){
if(is.numeric(df[i,11])==T){
lapply(df[i,11], all.neg)
}
}
}
}
我在 return 中不断收到以下错误消息:
Error in if (df[i, 7] == "Left" | df[i, 7] == "L") { :
missing value where TRUE/FALSE needed
我尝试执行 na.pass(df) 以避免在缺少值后停止,并且我包含了 is.na() 的第一个 if 语句,这似乎是不必要的。我也检查过并确保没有其他值(如“Null”)没有被正确编码为 NA。如果有人知道如何解决此问题,我将不胜感激 - 非常感谢!
这是数据的截图。基本上,如果 LSTOA 方向为左或 L,我需要将所有值更改为负数。
enter image description here
这里是数据的头部:
structure(list(`LSTOA Direction` = c("Left", "Left", "Left",
"Right", "Left", "Left"), `Preop PA` = c(NA, "6.5", "13.3", NA,
NA, "11.0"), `1st Erect` = c(NA, NA, "2.8", NA, "7.6", "2.8"),
`6M PO PA` = c(NA_character_, NA_character_, NA_character_,
NA_character_, NA_character_, NA_character_), `1Y PO PA` = c("7.5",
NA, "3.3", "5.5", NA, NA), `2Y PO PA` = c(NA, NA, "0.1",
"5.8", "7.2", "2.5"), `5Y PO PA` = c(NA, NA, NA, "3.9", "4.4",
NA), `10Y PO PA` = c("7.8", NA, NA, "2.6", NA, NA), `15Y PO PA` = c(NA,
NA, NA, "3.2", NA, NA)), row.names = c(NA, -6L), class = c("tbl_df",
"tbl", "data.frame"))
示例数据。
dat <- data.frame(A=c("L","Right","R","Left"), B=1:4, C=11:14, D=LETTERS[1:4])
dat
# A B C D
# 1 L 1 11 A
# 2 Right 2 12 B
# 3 R 3 13 C
# 4 Left 4 14 D
基础 R
mult <- 1-2*grepl("^L", dat$A)
mult
# [1] -1 1 1 -1
isnum <- sapply(dat, is.numeric)
isnum
# A B C D
# FALSE TRUE TRUE FALSE
dat[isnum] <- lapply(dat[isnum], `*`, must)
# *** output flushed ***
dat[isnum] <- lapply(dat[isnum], `*`, mult)
dat
# A B C D
# 1 L -1 -11 A
# 2 Right 2 12 B
# 3 R 3 13 C
# 4 Left -4 -14 D
dplyr
library(dplyr)
dat %>%
mutate(across(where(is.numeric), ~ if_else(grepl("^L", A), -1, 1) * .))
# A B C D
# 1 L -1 -11 A
# 2 Right 2 12 B
# 3 R 3 13 C
# 4 Left -4 -14 D
如果你有一个 data.frame,其中有两列,一列在第 7 个位置有方向指示器,一列在第 11 个位置有你想要变为负数的数值,那么试试这个“矢量化" 重新赋值
#Copy the column to be altered
df$newval <- df[[11]]
df$newval[ grepl("^L", df[[7]]) ] <- -abs( df$newval[ grepl("^L", df[[7]]) ])
LHS 和 RHS 具有相同的逻辑索引,当第一个字母是大写“L”时将为 TRUE,因此只有那些值得到否定处理。它现在将为负数(即使开始时为负数。)如果您不希望出现这种情况,则删除 abs
它将成为符号反转值。如果使用矢量化方法绕过循环,我在这里做什么。有一个逻辑向量,grepl("^L", df[[7]])
,决定行值是否会被修改。
有几点可以改进您的编码。永远不要使用 T 和 F。如果您忘记了可以用非逻辑值替换它们,它们会让您感到困惑。 TRUE 和 FALSE 永远无法重新定义。当您使用 is.numeric
时,测试是否等于 T 或 TRUE 是没有用的。使用 is.numeric(df[i,11])
而不是 is.numeric(df[i,11])==T
。但是,您不想在进行行测试或行分配的外观中使用 is.numeric。矢量是全数字或非数字的。在循环外测试以获得更高的效率。我看到 r2evans 提供了一个 MCVE 用于测试。请注意,他将其命名为 dat
,这是您应该遵循的做法。否则您将继续看到错误:Error in df[[2]] : object of type 'closure' is not subsettable
在您意识到 df
是 F 分布密度的函数名称之前,这没有任何意义。
我的 R 数据框中的一列有一个方向(左、右、L 或 R)。如果此列中的一行是 Left 或 L,我试图将不同列中同一行中的数字转换为负值。这是我到目前为止编写的代码:
for(i in 1:nrow(df)){
if(is.na(df[i,7]==F)){
if(df[i,7]=="Left" | df[i,7]=="L"){
if(is.numeric(df[i,11])==T){
lapply(df[i,11], all.neg)
}
}
}
}
我在 return 中不断收到以下错误消息:
Error in if (df[i, 7] == "Left" | df[i, 7] == "L") { :
missing value where TRUE/FALSE needed
我尝试执行 na.pass(df) 以避免在缺少值后停止,并且我包含了 is.na() 的第一个 if 语句,这似乎是不必要的。我也检查过并确保没有其他值(如“Null”)没有被正确编码为 NA。如果有人知道如何解决此问题,我将不胜感激 - 非常感谢!
这是数据的截图。基本上,如果 LSTOA 方向为左或 L,我需要将所有值更改为负数。 enter image description here
这里是数据的头部:
structure(list(`LSTOA Direction` = c("Left", "Left", "Left",
"Right", "Left", "Left"), `Preop PA` = c(NA, "6.5", "13.3", NA,
NA, "11.0"), `1st Erect` = c(NA, NA, "2.8", NA, "7.6", "2.8"),
`6M PO PA` = c(NA_character_, NA_character_, NA_character_,
NA_character_, NA_character_, NA_character_), `1Y PO PA` = c("7.5",
NA, "3.3", "5.5", NA, NA), `2Y PO PA` = c(NA, NA, "0.1",
"5.8", "7.2", "2.5"), `5Y PO PA` = c(NA, NA, NA, "3.9", "4.4",
NA), `10Y PO PA` = c("7.8", NA, NA, "2.6", NA, NA), `15Y PO PA` = c(NA,
NA, NA, "3.2", NA, NA)), row.names = c(NA, -6L), class = c("tbl_df",
"tbl", "data.frame"))
示例数据。
dat <- data.frame(A=c("L","Right","R","Left"), B=1:4, C=11:14, D=LETTERS[1:4])
dat
# A B C D
# 1 L 1 11 A
# 2 Right 2 12 B
# 3 R 3 13 C
# 4 Left 4 14 D
基础 R
mult <- 1-2*grepl("^L", dat$A)
mult
# [1] -1 1 1 -1
isnum <- sapply(dat, is.numeric)
isnum
# A B C D
# FALSE TRUE TRUE FALSE
dat[isnum] <- lapply(dat[isnum], `*`, must)
# *** output flushed ***
dat[isnum] <- lapply(dat[isnum], `*`, mult)
dat
# A B C D
# 1 L -1 -11 A
# 2 Right 2 12 B
# 3 R 3 13 C
# 4 Left -4 -14 D
dplyr
library(dplyr)
dat %>%
mutate(across(where(is.numeric), ~ if_else(grepl("^L", A), -1, 1) * .))
# A B C D
# 1 L -1 -11 A
# 2 Right 2 12 B
# 3 R 3 13 C
# 4 Left -4 -14 D
如果你有一个 data.frame,其中有两列,一列在第 7 个位置有方向指示器,一列在第 11 个位置有你想要变为负数的数值,那么试试这个“矢量化" 重新赋值
#Copy the column to be altered
df$newval <- df[[11]]
df$newval[ grepl("^L", df[[7]]) ] <- -abs( df$newval[ grepl("^L", df[[7]]) ])
LHS 和 RHS 具有相同的逻辑索引,当第一个字母是大写“L”时将为 TRUE,因此只有那些值得到否定处理。它现在将为负数(即使开始时为负数。)如果您不希望出现这种情况,则删除 abs
它将成为符号反转值。如果使用矢量化方法绕过循环,我在这里做什么。有一个逻辑向量,grepl("^L", df[[7]])
,决定行值是否会被修改。
有几点可以改进您的编码。永远不要使用 T 和 F。如果您忘记了可以用非逻辑值替换它们,它们会让您感到困惑。 TRUE 和 FALSE 永远无法重新定义。当您使用 is.numeric
时,测试是否等于 T 或 TRUE 是没有用的。使用 is.numeric(df[i,11])
而不是 is.numeric(df[i,11])==T
。但是,您不想在进行行测试或行分配的外观中使用 is.numeric。矢量是全数字或非数字的。在循环外测试以获得更高的效率。我看到 r2evans 提供了一个 MCVE 用于测试。请注意,他将其命名为 dat
,这是您应该遵循的做法。否则您将继续看到错误:Error in df[[2]] : object of type 'closure' is not subsettable
在您意识到 df
是 F 分布密度的函数名称之前,这没有任何意义。