根据数据框中的某些条件应用计算

时间:2015-10-13 06:05:37

标签: r dataframe with-statement

我有以下数据框:

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      

我想根据特定条件将mean2FLAG列添加到数据框中。条件如下:

1)如果存在mean1sd,请将相同的值复制到mean2列并为其提供FLAG ==1

2)如果mean1sdNAmedian:IQR_75存在,则为mean2设置等于20的值,并为其FLAG==2 }。注意:值20是任意的。我将改为使用等式,但这是为了使这里的问题变得容易。

3)如果mean1sdNAmedian, RANGE_min, RANGE_max存在,则为mean2设置等于30的值,并为其{{}} 1}}。

结果应如下所示:

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

我会请求你的帮助来实现我的目标,这样我就可以将它应用到我的大数据集上。

3 个答案:

答案 0 :(得分:4)

使用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)]

答案 1 :(得分:2)

我们可以根据指定列中的NA元素创建几个逻辑索引。如果'mean1'和'SD'都不是NA,则'indx'给出TRUE,如果'median:IQR_75'列的行中没有NA值,则'indx2'将为TRUE,因为我们正在采用{{1} NA元素。类似地,'indx3'为列的中位数:range_max'的非NA元素赋予TRUE。

rowSums

现在我们可以通过算术运算创建一个数字索引,以创建一个唯一索引('indx4'),可用于填充值1.5,30,20或1:3。

 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 <- 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

答案 2 :(得分:2)

试试这个:

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