如何使用基于R的数字向量的现有数据框和范围创建新数据框。

时间:2018-01-25 22:53:08

标签: r

我有一个96 x 48的数据帧df。第一列是标识字段(char),第2-48列是数值。我还有两个数字向量,每个向量有96个元素,由对应每行的上限和下限组成。

我想创建一个具有相同列1的新数据帧,但是对于列2-48,我想看看该值是否在每行的两个向量中的值之间。然后我想在新数据框中有1,如果是,则为0,如果不是(排序的布尔值)。

示例:

df:


    1  2  3  4 .. 48
    a  7  11 15   58
    b  6  9  13   46
    c  8  14 20   73 

载体:


    upper: 24, 35, 22, 63
    lower: 10, 11, 12, 11


返回:


    1  2  3  4 .. 48  
    a  0  1  1    0   (between upper[1] and lower[1])
    b  0  0  1    0   (between upper[2] and lower[2])
    c  0  1  1    0   ...

我想在没有循环的情况下这样做,因为我非常确定这是一种方法,但我似乎无法找到它。

5 个答案:

答案 0 :(得分:2)

使用dplyr的一种方法:

# Data
df <- data.frame(id=letters[1:3], col2=c(7,6,8), col3=c(11,9,14), col4=c(15,13,20), col48=c(58,46,73))

# chain of operations
library(dplyr)
df %>%
  mutate(upper = c(24, 35, 22), lower = c(10, 11, 12)) %>%
  mutate_at(paste0("col", c(2:4, 48)), funs(.>=lower & .<=upper)) %>%
  mutate_at(paste0("col", c(2:4, 48)), as.integer) %>%
  select(-lower, -upper)

输出:

  col1 col2 col3 col4 col48
1    a    0    1    1     0
2    b    0    0    1     0
3    c    0    1    1     0

答案 1 :(得分:2)

因为你说其他变量是数字的,所以我们可以这样做:

In ('')

无需ifelse(t(upper.bounds-t(df[-1])>0&lower.bounds-t(df[-1])<0),1,0) c2 c3 c4 c48 [1,] 0 0 1 0 [2,] 0 0 1 0 [3,] 0 1 1 0 lapply 数据在哪里:

forloop

答案 2 :(得分:1)

通过使用遍历所有列的for隐式循环,可以避免显式lappy循环。如果循环遍历列,我认为从性能的角度来看,循环是关键的,但只有当你遍历行时(因为R将列的元素作为向量存储在连续内存中)位置,以便性能最佳,但每行的元素在内存位置上扩展,导致性能损失,以循环遍1行1):

df <- data.frame(c1 = c(7, 6, 8), c2 = c(11, 9, 14), c3 = c(15, 13, 20), c48 = c(58, 46, 73))
df

lower.bounds <- c(10, 11, 12) # , 11)
upper.bounds <- c(24, 35, 22) # , 63)

res <- lapply(df, function(col) {ifelse(col >= lower.bounds & col <= upper.bounds, 1, 0)})
as.data.frame(res)
# c1 c2 c3 c48
# 1  0  1  1   0
# 2  0  0  1   0
# 3  0  1  1   0

答案 3 :(得分:1)

另一个选择是只使用apply over columns。我觉得这很简单干净。

df <- data.frame(V2=c(7,6,8), V3=c(11,9,14), V4=c(15,13,20), V48=c(58,46,73))

upper <- c(24, 35, 22)
lower <- c(10, 11, 12)

data.frame(apply(df,2,function(x)((upper>=x)*(x>=lower))))
  V2 V3 V4 V48
  1  0  1  1   0
  2  0  0  1   0
  3  0  1  1   0

编辑:在MKR评论之后,我变得很好奇,不得不测试性能。如果有任何关于如何以不同方式衡量它的建议,请发表评论。

df <- data.frame(V2=c(7,6,8), V3=c(11,9,14), V4=c(15,13,20), V48=c(58,46,73))

upper <- c(24, 35, 22)
lower <- c(10, 11, 12)

 start.time <- Sys.time()
 data.frame(apply(df,2,function(x)((upper>=x)*(x>=lower))))
  #V2 V3 V4 V48
  #1  0  1  1   0
  #2  0  0  1   0
  #3  0  1  1   0
 Sys.time()-start.time
  #Time difference of 0.0146079 secs

 start.time <- Sys.time()
 data.frame(apply(df,2,function(x)(as.numeric((upper>=x)&(x>=lower)))))
  #V2 V3 V4 V48
  #1  0  1  1   0
  #2  0  0  1   0
  #3  0  1  1   0
 Sys.time()-start.time
  #Time difference of 0.0124476 secs

 start.time <- Sys.time()
 data.frame(ifelse(upper > df[] & lower < df[], 1, 0))
  #V2 V3 V4 V48
  #1  0  1  1   0
  #2  0  0  1   0
  #3  0  1  1   0
 Sys.time()-start.time
  #Time difference of 0.008914948 secs

答案 4 :(得分:1)

另一种可能更简单的解决方案可能是:

UnityConfig.RegisterTypes()

OR

    df <- data.frame(c1 = c(7, 6, 8), 
                     c2 = c(11, 9, 14), 
                     c3 = c(15, 13, 20), 
                     c48 = c(58, 46, 73))

    lower.bounds <- c(10, 11, 12)
    upper.bounds <- c(24, 35, 22)

    ifelse(upper.bounds > df[] & lower.bounds < df[], 1, 0)
  # Result:
  #       c1 c2 c3 c48
  #  [1,]  0  1  1   0
  #  [2,]  0  0  1   0
  #  [3,]  0  1  1   0