0

I have two columns, weight and area. I want to create two columns as follows:

  1. out1: If weight > 12, top, else down.
  2. out2: If area > -0.5, insert a value of 0. Otherwise round the absolute value of area with 0.5 mapping to 1.

Desired output:

       weight   area    out1    out2
           12      3    down       0
           13   -0.4     top       0
           11    2.5    down       0
           17   -0.5     top       1
           16   -3.7     top       4
           14   -1.2     top       1
           11   -4.8    down       5
JasonAizkalns
  • 20,243
  • 8
  • 57
  • 116

3 Answers3

1

Try

transform(df, out1=c('down', 'top')[(weight>12)+1L], 
                   out2= ifelse(area >-0.5, 0, abs(round2(area,0))))
#   weight area out1 out2
#1     12  3.0 down    0
#2     13 -0.4  top    0
#3     11  2.5 down    0
#4     17 -0.5  top    1
#5     16 -3.7  top    4
#6     14 -1.2  top    1
#7     11 -4.8 down    5

Or

library(data.table)
setDT(df)[, paste0('out',1:2) := list(c('down', 'top')[(weight>12)+1L],
               ifelse(area > -0.5, 0, abs(round2(area,0))))][]

where round2 is (taken from Round up from .5 in R)

  round2 = function(x, n) {
  posneg = sign(x)
  z = abs(x)*10^n
  z = z + 0.5
  z = trunc(z)
  z = z/10^n
  z*posneg
   }
Community
  • 1
  • 1
akrun
  • 874,273
  • 37
  • 540
  • 662
  • Am I right in thinking that this won't round the -0.5 to -1 ... see http://stackoverflow.com/questions/12688717/round-up-from-5-in-r – jalapic Mar 03 '15 at 18:47
  • @jalapic Yes, the one in the link `round2` gives the expected result here – akrun Mar 03 '15 at 18:50
  • @user2684423 replace `round` by `round2` from the link jalapic provided to get the expected result as you showed – akrun Mar 03 '15 at 18:51
  • can you provide codes, i have used that link, but i got error –  Mar 03 '15 at 19:05
  • out 1 is ok- problem continue with out2, the values are different. Can you help please –  Mar 03 '15 at 19:16
  • @user2684423 Which values are different? Initially, you had `-1` for the 4th row. I don't know how it changes to 1 now – akrun Mar 03 '15 at 19:18
  • @user2684423 Just wrap it with `abs`. Updated the post – akrun Mar 03 '15 at 19:50
  • can you do it with data table please –  Mar 03 '15 at 19:57
  • @user2684423 Isn't that already posted there? `setDT(df)[, paste0('out',1:2) := list(c('down', 'top')[(weight>12)+1L], ifelse(area > -0.5, 0, abs(round2(area,0))))][]` – akrun Mar 03 '15 at 20:00
1

Here's how I'd do this using data.table:

require(data.table)
dt[, out1 := "down"][weight > 12, out1 := "top"]
dt[, out2 := floor(abs(area)+0.5)][area > -0.5, out2 := 0]
#    weight area out1 out2
# 1:     12  3.0 down    0
# 2:     13 -0.4  top    0
# 3:     11  2.5 down    0
# 4:     17 -0.5  top    1
# 5:     16 -3.7  top    4
# 6:     14 -1.2  top    1
# 7:     11 -4.8 down    5
Arun
  • 116,683
  • 26
  • 284
  • 387
0
df <- data.frame(weight= c(12, 13, 11, 17, 16, 14, 11),
                 area  = c(3, -0.4, 2.5, -0.5, -3.7, -1.2, -4.8))

df$out1 <- ifelse(df$weight > 12, "top", "down")
df$out2 <- ifelse(df$area > -0.5, 0, floor(0.5 + abs(df$area)))

df

#   weight area out1 out2
# 1     12  3.0 down    0
# 2     13 -0.4  top    0
# 3     11  2.5 down    0
# 4     17 -0.5  top    1
# 5     16 -3.7  top    4
# 6     14 -1.2  top    1
# 7     11 -4.8 down    5
JasonAizkalns
  • 20,243
  • 8
  • 57
  • 116