根据其他列在数据框中创建列

时间:2017-06-16 10:59:01

标签: r dataframe

我有一个有4列的数据框。在这4列中,2列是下限值和上限值。对于剩余的2列,我需要创建相应的2列,如果列中的值小于下限,则包含-1,如果高于上限,则为+1,如果高于上限,则为0。下面是我的输入(我想将encode2_列与lcl和ucl进行比较)。

input

我希望输出(带有前缀encode3_的列)类似于

enter image description here

我有744个这样的变量,我需要创建744个相应的变量。我尝试过使用apply但不是任何结果。在这方面有任何帮助吗?

2 个答案:

答案 0 :(得分:1)

可重现的代码会有所帮助,但我认为这正是您所寻找的。 if_else嵌套在if_else

df <- data.frame(lcl=c(10,10,10), ucl=c(100,100,100), 
                 Salary=c(2, 20, 200),
                 Salary33=c(3,30,300),
                 Salary77=c(4, 40, 400))

library(dplyr)


    fun <-function(x, y, z) {if_else(x<y,-1,
                         if_else(x>z, 1,0))}

    df %>% mutate_at(vars(Salary:Salary77), funs(Encode3=fun(., y=lcl, z=ucl)) )

     lcl ucl Salary Salary33 Salary77 Salary_Encode3 Salary33_Encode3 Salary77_Encode3
    1  10 100      2        3        4             -1               -1               -1
    2  10 100     20       30       40              0                0                0
    3  10 100    200      300      400              1                1                1

答案 1 :(得分:1)

这是典型的情况,其中便于数据输入和检查的Excel风格的宽格式不利于有效的数据处理。如果有许多列包含相同的数据,那么以SQL样式的长格式重新整形数据通常会更有效。为此,使用dcast()包中的melt()data.table

library(data.table)   # CRAN version 1.10.4 used
# coerce to data.table class, add a row number column,
# reshape from wide to long format all columns starting with Encode2_SALARY_
long <- melt(setDT(DT)[, rn := .I], measure.vars = patterns("Encode2_SALARY_"),
             value.name = "Encode2_SALARY")
# rename variable names
long[, variable := stringr::str_replace(variable, "Encode2_SALARY_", "")]
# show intermediate result
long[]

这是我们到目前为止所得到的:

      lcl    ucl rn variable Encode2_SALARY
 1: 40168  46551  1        1          80984
 2: 57212 109839  2        1          42651
 3: 77285 114468  3        1          86248
 4: 86080 110821  4        1          94611
 5: 40168  46551  1        2          89193
 6: 57212 109839  2        2          59820
 7: 77285 114468  3        2         120393
 8: 86080 110821  4        2          82995
 9: 40168  46551  1      744          49292
10: 57212 109839  2      744           3823
11: 77285 114468  3      744         107498
12: 86080 110821  4      744          68502

现在,计算新的编码。请注意,没有使用嵌套的ifelse,但逻辑值可以强制转换为整数(TRUE的事实变为1,FALSE 0)并且lcl小于或等于ucl

long[, Encode3_SALARY := 1L - (Encode2_SALARY < lcl) - (Encode2_SALARY < ucl)]
long[]

产生

      lcl    ucl rn variable Encode2_SALARY Encode3_SALARY
 1: 40168  46551  1        1          80984              1
 2: 57212 109839  2        1          42651             -1
 3: 77285 114468  3        1          86248              0
 4: 86080 110821  4        1          94611              0
 5: 40168  46551  1        2          89193              1
 6: 57212 109839  2        2          59820              0
 7: 77285 114468  3        2         120393              1
 8: 86080 110821  4        2          82995             -1
 9: 40168  46551  1      744          49292              1
10: 57212 109839  2      744           3823             -1
11: 77285 114468  3      744         107498              0
12: 86080 110821  4      744          68502             -1

通常,其他处理步骤将采用长格式。但是,OP要求以宽格式获得结果。

dcast(long, rn + lcl + ucl ~ variable, value.var = c("Encode2_SALARY", "Encode3_SALARY"))

返回:

   rn   lcl    ucl Encode2_SALARY_1 Encode2_SALARY_2 Encode2_SALARY_744 Encode3_SALARY_1
1:  1 40168  46551            80984            89193              49292                1
2:  2 57212 109839            42651            59820               3823               -1
3:  3 77285 114468            86248           120393             107498                0
4:  4 86080 110821            94611            82995              68502                0
   Encode3_SALARY_2 Encode3_SALARY_744
1:                1                  1
2:                0                 -1
3:                1                  0
4:               -1                 -1

代码应该使用任意数量的行和列(提供足够的RAM)。

数据

由于该问题没有提供可重现的数据,因此下面的代码用于创建样本数据:

library(data.table)   # CRAN verion 1.10.4 used

set.seed(1L)   ### This is important for reproducible sample data
n_rows <- 4L
sal_min <-  20000
sal_max <- 120000
DT <- data.table(lcl = runif(n_rows, sal_min, sal_max),
                 ucl = runif(n_rows, sal_min, sal_max))
# create column names
cols <- paste0("Encode2_SALARY_", c(1:2, 744L))
# create columns with random salaries
DT[, (cols) := lapply(cols, function(x) abs(rnorm(n_rows, 
                      mean(c(sal_min, sal_max)),
                      sd = (sal_max - sal_min)/3.0)))]
# round all columns to improve readability
DT[, (names(DT)) := lapply(.SD, round)]
# make sure that lcl <= ucl - after rounding !
DT[, `:=`(lcl = pmin(lcl, ucl), ucl = pmax(lcl, ucl))][]
DT[]

产生

     lcl    ucl Encode2_SALARY_1 Encode2_SALARY_2 Encode2_SALARY_744
1: 40168  46551            80984            89193              49292
2: 57212 109839            42651            59820               3823
3: 77285 114468            86248           120393             107498
4: 86080 110821            94611            82995              68502