我有一个有4列的数据框。在这4列中,2列是下限值和上限值。对于剩余的2列,我需要创建相应的2列,如果列中的值小于下限,则包含-1,如果高于上限,则为+1,如果高于上限,则为0。下面是我的输入(我想将encode2_列与lcl和ucl进行比较)。
我希望输出(带有前缀encode3_的列)类似于
我有744个这样的变量,我需要创建744个相应的变量。我尝试过使用apply但不是任何结果。在这方面有任何帮助吗?
答案 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