根据数据框中的特定条件应用计算
Apply calculations based on certain conditions in a data frame
我有以下数据框:
Source mean1 SD median range_min range_max IQR_25 IQR_75
1 1.5 0.2 3 NA NA NA NA
2 NA NA 2 1 5 1.5 4
3 NA NA 4 2 7 NA NA
我想根据特定条件将 mean2
和 FLAG
列添加到数据框中。条件如下:
1) 如果存在 mean1
和 sd
则将相同的值复制到 mean2
列中并给它 FLAG ==1
2) 如果 mean1
和 sd
是 NA
但 median:IQR_75
存在则将 mean2
的值等于 20 并给它一个 FLAG==2
。注意:值 20 是任意的。我将用一个等式来代替,但这是为了让这里的问题更容易。
3) 如果如果 mean1
和 sd
是 NA
但 median, RANGE_min, RANGE_max
存在则将 mean2
的值等于 30 并给它一个FLAG==3
.
结果应如下所示:
Source mean1 SD median range_min range_max IQR_25 IQR_75 mean2 FLAG
1 1.5 0.2 3 NA NA NA NA 1.5 1
2 NA NA 2 1 5 1.5 4 20 2
3 NA NA 4 2 7 NA NA 30 3
我尝试了以下方法,但使用起来不太顺利:
df$mean2 <- with(df, (is.na(mean1)==F&(is.na(SD)==F))*mean1+ (is.na(mean1)==T & is.na(SD)==T & is.na(median)==F &
is.na(range_min)==F & is.na(range_max)==F & is.na(IQR_25)==F &
is.na(IQR_75)==F)*20)
我会请你帮助实现我的目标,这样我就可以将它应用到我的大数据集上。
我们可以根据指定列中的 NA 元素创建几个逻辑索引。如果 'mean1' 和 'SD' 都不是 NA,'indx' 给出 TRUE,如果 'median:IQR_75' 列的行中没有 NA 值,'indx2' 将为 TRUE我们正在使用 NA 元素的 rowSums
。同样,'indx3' 为列 'median:range_max'.
的非 NA 元素提供 TRUE
indx <- rowSums(!is.na(df1[c('mean1', 'SD')]))==2
indx2 <- !rowSums(is.na(df1[4:ncol(df1)]))
indx3 <- !rowSums(is.na(df1[4:6]))
现在我们可以通过算术运算创建一个数字索引来创建一个唯一索引('indx4'),它可以用来填充值1.5、30、20或1:3。
indx4 <- as.numeric(factor(1+2*indx+4*indx2+8*indx3))
c(1.5, 30, 20)[indx4]
#[1] 1.5 20.0 30.0
c(1,3,2)[indx4]
#[1] 1 2 3
或者我们使用嵌套 ifelse
df1$mean2 <- ifelse(indx, 1.5, ifelse(indx2, 20, ifelse(indx3, 30, NA)))
df1$mean2
#[1] 1.5 20.0 30.0
df1$FLAG <- ifelse(indx, 1, ifelse(indx2, 2, ifelse(indx3, 3, NA)))
df1$FLAG
# [1] 1 2 3
df1
# Source mean1 SD median range_min range_max IQR_25 IQR_75 mean2 FLAG
#1 1 1.5 0.2 3 NA NA NA NA 1.5 1
#2 2 NA NA 2 1 5 1.5 4 20.0 2
#3 3 NA NA 4 2 7 NA NA 30.0 3
数据
df1 <- structure(list(Source = 1:3, mean1 = c(1.5, NA, NA), SD = c(0.2,
NA, NA), median = c(3L, 2L, 4L), range_min = c(NA, 1L, 2L),
range_max = c(NA,
5L, 7L), IQR_25 = c(NA, 1.5, NA), IQR_75 = c(NA, 4L, NA)),
.Names = c("Source",
"mean1", "SD", "median", "range_min", "range_max", "IQR_25",
"IQR_75"), class = "data.frame", row.names = c(NA, -3L))
使用 data.table
包,您可以按如下方式进行:
library(data.table)
setDT(df)[!is.na(mean1) & !is.na(SD), `:=` (mean2 = mean1, Flag = 1)
][is.na(mean1) & is.na(SD) & complete.cases(median,range_min,range_max,IQR_25,IQR_75),
`:=` (mean2 = 20, Flag = 2)
][is.na(mean1) & is.na(SD) & complete.cases(median,range_min,range_max) & is.na(IQR_25) & is.na(IQR_75),
`:=` (mean2 = 30, Flag = 3)]
这给出:
> df
Source mean1 SD median range_min range_max IQR_25 IQR_75 mean2 Flag
1: 1 1.5 0.2 3 NA NA NA NA 1.5 1
2: 2 NA NA 2 1 5 1.5 4 20.0 2
3: 3 NA NA 4 2 7 NA NA 30.0 3
或者,您可以预先为您的多个条件创建索引。这将提供更清晰的 data.table
语法:
indx1 <- complete.cases(df[c("mean1", "SD")])
indx2 <- complete.cases(df[c("median","range_min","range_max","IQR_25","IQR_75")])
indx3 <- !complete.cases(df[c("IQR_25","IQR_75")]) & complete.cases(df[c("median","range_min","range_max")])
library(data.table)
setDT(df)[indx1, `:=` (mean2 = mean1, Flag = 1)
][!indx1 & indx2, `:=` (mean2 = 20, Flag = 2)
][!indx1 & indx3, `:=` (mean2 = 30, Flag = 3)]
试试这个:
df$mean2 = NA
df$FLAG = NA
ind1 = complete.cases(df[, c("mean1", "SD")])
ind2 = complete.cases(df[, c("median", "range_min", "range_max", "IQR_25", "IQR_75")])
ind3 = complete.cases(df[, c("median", "range_min", "range_max")])
df$mean2[ind1] = df$mean1[ind1]
df$mean2[!ind1 & ind2] = 20
df$mean2[!ind1 & !ind2 & ind3] = 30
df$FLAG[ind1] = 1
df$FLAG[!ind1 & ind2] = 2
df$FLAG[!ind1 & !ind2 & ind3] = 3
我有以下数据框:
Source mean1 SD median range_min range_max IQR_25 IQR_75
1 1.5 0.2 3 NA NA NA NA
2 NA NA 2 1 5 1.5 4
3 NA NA 4 2 7 NA NA
我想根据特定条件将 mean2
和 FLAG
列添加到数据框中。条件如下:
1) 如果存在 mean1
和 sd
则将相同的值复制到 mean2
列中并给它 FLAG ==1
2) 如果 mean1
和 sd
是 NA
但 median:IQR_75
存在则将 mean2
的值等于 20 并给它一个 FLAG==2
。注意:值 20 是任意的。我将用一个等式来代替,但这是为了让这里的问题更容易。
3) 如果如果 mean1
和 sd
是 NA
但 median, RANGE_min, RANGE_max
存在则将 mean2
的值等于 30 并给它一个FLAG==3
.
结果应如下所示:
Source mean1 SD median range_min range_max IQR_25 IQR_75 mean2 FLAG
1 1.5 0.2 3 NA NA NA NA 1.5 1
2 NA NA 2 1 5 1.5 4 20 2
3 NA NA 4 2 7 NA NA 30 3
我尝试了以下方法,但使用起来不太顺利:
df$mean2 <- with(df, (is.na(mean1)==F&(is.na(SD)==F))*mean1+ (is.na(mean1)==T & is.na(SD)==T & is.na(median)==F &
is.na(range_min)==F & is.na(range_max)==F & is.na(IQR_25)==F &
is.na(IQR_75)==F)*20)
我会请你帮助实现我的目标,这样我就可以将它应用到我的大数据集上。
我们可以根据指定列中的 NA 元素创建几个逻辑索引。如果 'mean1' 和 'SD' 都不是 NA,'indx' 给出 TRUE,如果 'median:IQR_75' 列的行中没有 NA 值,'indx2' 将为 TRUE我们正在使用 NA 元素的 rowSums
。同样,'indx3' 为列 'median:range_max'.
indx <- rowSums(!is.na(df1[c('mean1', 'SD')]))==2
indx2 <- !rowSums(is.na(df1[4:ncol(df1)]))
indx3 <- !rowSums(is.na(df1[4:6]))
现在我们可以通过算术运算创建一个数字索引来创建一个唯一索引('indx4'),它可以用来填充值1.5、30、20或1:3。
indx4 <- as.numeric(factor(1+2*indx+4*indx2+8*indx3))
c(1.5, 30, 20)[indx4]
#[1] 1.5 20.0 30.0
c(1,3,2)[indx4]
#[1] 1 2 3
或者我们使用嵌套 ifelse
df1$mean2 <- ifelse(indx, 1.5, ifelse(indx2, 20, ifelse(indx3, 30, NA)))
df1$mean2
#[1] 1.5 20.0 30.0
df1$FLAG <- ifelse(indx, 1, ifelse(indx2, 2, ifelse(indx3, 3, NA)))
df1$FLAG
# [1] 1 2 3
df1
# Source mean1 SD median range_min range_max IQR_25 IQR_75 mean2 FLAG
#1 1 1.5 0.2 3 NA NA NA NA 1.5 1
#2 2 NA NA 2 1 5 1.5 4 20.0 2
#3 3 NA NA 4 2 7 NA NA 30.0 3
数据
df1 <- structure(list(Source = 1:3, mean1 = c(1.5, NA, NA), SD = c(0.2,
NA, NA), median = c(3L, 2L, 4L), range_min = c(NA, 1L, 2L),
range_max = c(NA,
5L, 7L), IQR_25 = c(NA, 1.5, NA), IQR_75 = c(NA, 4L, NA)),
.Names = c("Source",
"mean1", "SD", "median", "range_min", "range_max", "IQR_25",
"IQR_75"), class = "data.frame", row.names = c(NA, -3L))
使用 data.table
包,您可以按如下方式进行:
library(data.table)
setDT(df)[!is.na(mean1) & !is.na(SD), `:=` (mean2 = mean1, Flag = 1)
][is.na(mean1) & is.na(SD) & complete.cases(median,range_min,range_max,IQR_25,IQR_75),
`:=` (mean2 = 20, Flag = 2)
][is.na(mean1) & is.na(SD) & complete.cases(median,range_min,range_max) & is.na(IQR_25) & is.na(IQR_75),
`:=` (mean2 = 30, Flag = 3)]
这给出:
> df
Source mean1 SD median range_min range_max IQR_25 IQR_75 mean2 Flag
1: 1 1.5 0.2 3 NA NA NA NA 1.5 1
2: 2 NA NA 2 1 5 1.5 4 20.0 2
3: 3 NA NA 4 2 7 NA NA 30.0 3
或者,您可以预先为您的多个条件创建索引。这将提供更清晰的 data.table
语法:
indx1 <- complete.cases(df[c("mean1", "SD")])
indx2 <- complete.cases(df[c("median","range_min","range_max","IQR_25","IQR_75")])
indx3 <- !complete.cases(df[c("IQR_25","IQR_75")]) & complete.cases(df[c("median","range_min","range_max")])
library(data.table)
setDT(df)[indx1, `:=` (mean2 = mean1, Flag = 1)
][!indx1 & indx2, `:=` (mean2 = 20, Flag = 2)
][!indx1 & indx3, `:=` (mean2 = 30, Flag = 3)]
试试这个:
df$mean2 = NA
df$FLAG = NA
ind1 = complete.cases(df[, c("mean1", "SD")])
ind2 = complete.cases(df[, c("median", "range_min", "range_max", "IQR_25", "IQR_75")])
ind3 = complete.cases(df[, c("median", "range_min", "range_max")])
df$mean2[ind1] = df$mean1[ind1]
df$mean2[!ind1 & ind2] = 20
df$mean2[!ind1 & !ind2 & ind3] = 30
df$FLAG[ind1] = 1
df$FLAG[!ind1 & ind2] = 2
df$FLAG[!ind1 & !ind2 & ind3] = 3