将自定义函数应用于数据框

时间:2019-11-22 01:56:45

标签: r

需要帮助的地方不是太复杂,而是新的。 我有一个数据帧df,其中包含一列Product.id和一个价格Price。

Product.id  price
A   11.5
A   11.5
A   12
A   13
A   13
B   9.25
B   9.75
B   9.75
B   9.5

我想使用自定义功能检查价格是否比上个月有所变化:

Check.Price.Change <- function(Vector){
  for(x in 1:nrow(Vector)){
    if(Vector[x] != Vector[x-1]){
      TRUE 
    }
  }
}

检查存储桶与上个月相比是否有变化

df <- df %>%
  group_by(Product.id) %>%
  mutate(if.Price.change = lapply(Price, Check.Price.Change))

我收到错误消息:

Error in 1:nrow(Vector) : argument of length 0
Called from: FUN(X[[i]], ...)

请问正确的方法是什么?

2 个答案:

答案 0 :(得分:1)

我们可以使用lag中的dplyr与上一个条目进行比较。

library(dplyr)
df %>% group_by(Product.id) %>%  mutate(is_changed = price != lag(price))

# Product.id price is_changed
#  <fct>      <dbl> <lgl>     
#1 A          11.5  NA        
#2 A          11.5  FALSE     
#3 A          12    TRUE      
#4 A          13    TRUE      
#5 A          13    FALSE     
#6 B           9.25 NA        
#7 B           9.75 TRUE      
#8 B           9.75 FALSE     
#9 B           9.5  TRUE      

类似地,shift中有一个data.table函数,其默认type"lag"

library(data.table)
setDT(df)[, is_changed := price != shift(price), by = Product.id]

数据

df <- structure(list(Product.id = structure(c(1L, 1L, 1L, 1L, 1L, 2L, 
2L, 2L, 2L), .Label = c("A", "B"), class = "factor"), price = c(11.5, 
11.5, 12, 13, 13, 9.25, 9.75, 9.75, 9.5)), class = "data.frame", 
row.names = c(NA, -9L))

答案 1 :(得分:1)

如果上一个Price与当前行的价格匹配,则下面的代码将添加一个指示符列。 lag(和lead)是dplyr函数,可让您有效地比较不同行中列的值。也是来自dplyr的向量化if_else,如果满足条件,则将使值if.Price.change TRUE;如果不满足,则使值FALSE;如果不能满足则将得到NA比较。请注意,由于无法从前一行提取值,因此无法对第一行进行比较。附带说明一下,lag / lead让我们使用向前或向后比较多行,默认值为1。

使用dplyr:

df <- df %>% group_by(Product.id) %>%
              mutate(if.Price.change = if_else(lag(Price) == Price, TRUE, FALSE, NA) %>% ungroup
# A tibble: 9 x 3
#  Product.id Price if.Price.change
#  <fct>      <dbl> <lgl>          
#1 A          11.5  NA             
#2 A          11.5  TRUE           
#3 A          12    FALSE          
#4 A          13    FALSE          
#5 A          13    TRUE           
#6 B           9.25 NA             
#7 B           9.75 FALSE          
#8 B           9.75 TRUE           
#9 B           9.5  FALSE