遍历每一行

时间:2016-06-13 15:34:27

标签: r

我正在编写一个函数,但是我对R的向量结构略有混淆。

我有一个数据表,其中每个人都有产品和产品价值。我有一个层表,每个产品都有一个带有下限和上限的层,然后是一个返回值。

我想做以下事情:

  1. data.person
  2. 获取产品
  3. 仅在data.tiers
  4. 中查看该产品
  5. data.person
  6. 获取值
  7. 将它与第一层进行比较。如果值介于两者之间,则返回该值 底层和顶层。
  8. 再次为下一层做同样的事。
  9. 这是我走了多远:

    Employee <- c("Bob", "Dave", "Sarah")
    Product <- c("A", "B", "A")
    Value <- c(10, 20, 50)
    data.person <- data.frame(Employee, Product, Value)
    
    Product <- c("A", "A", "B", "B")
    Lower <- c(0,20,0,10)
    Upper <- c(20, 999, 10, 999)
    Return <- c(0.05, .1, 0.04, .08)
    data.tiers <- data.frame(Product, Lower, Upper, Return)
    
    myFunc <- function(product, value)
    {
      tiers.temp <- data.tiers %>% 
        filter(Product == product )
    
      result <- 0
    
      for (i in length(tiers.temp)){
    
        if(value >tiers.temp$Lower[i] & value <= tiers.temp$Tier.Upper[i]){
          result <- tiers.temp$Return[i] }
      }
    
      result
    
    }
    

    我的函数将产品向量和值向量作为输入。我想进入并过滤数据集中当前行上产品的data.tiers表。基于R的矢量性质,我不确定这是否是正确的方法。

    然后我遍历适用的层并执行测试并返回一个值,我需要将该值分配给data.person表中的列。

    预期结果:我的最终结果是来自data.tiers表格的数字向量。因此,数据集的第一行将返回0.05,因为10介于0和20之间。

    在这样的情况下获得有关最佳实践的信息会很好。

2 个答案:

答案 0 :(得分:1)

一种方法是使用dplyr::rowwise()并添加新列value_is_between,以表明ValueLower之间是否Upper

left_join(data.person, data.tiers, by = "Product") %>%
  rowwise() %>%
  mutate(value_is_between = between(Value, Lower, Upper)) %>%
  filter(value_is_between == TRUE)

#   Employee Product Value Lower Upper Return value_is_between
#     (fctr)  (fctr) (dbl) (dbl) (dbl)  (dbl)            (lgl)
# 1      Bob       A    10     0    20   0.05             TRUE
# 2     Dave       B    20    10   999   0.08             TRUE
# 3    Sarah       A    50    20   999   0.10             TRUE

答案 1 :(得分:1)

使用foverlaps中的data.table

require(data.table)
setDT(data.person)
setDT(data.tiers)
setkey(data.tiers,Product,Lower,Upper)
data.person[,Value2:=Value]
foverlaps(data.person,data.tiers,by.x=c("Product","Value","Value2"),
          by.y=c("Product","Lower","Upper"))[,
                  c("Value2","Lower","Upper"):=NULL][]   
#   Product Return Employee Value
#1:       A   0.05      Bob    10
#2:       B   0.08     Dave    20
#3:       A   0.10    Sarah    50