2017-01-03 15 views
0

私は2つのデータセットを持っています: competitor_data - 競合他社価格が収集された価格と日付だけでなく、特定の製品の競合他社も含まれています。入れ子ループの代わりにR

product_price - 各価格変更の日付。 PRODUCT_PRICE内の指定された製品については

competitor_data <- data.frame(productId=c('banana', 'banana','banana', 'banana','banana', 'banana','fig', 'fig','fig', 'fig','fig', 'fig'), 
          crawl_date=c("2014-04-05", "2014-04-22", "2014-05-05", "2014-05-22","2014-06-05", "2014-06-22", 
            "2014-05-08", "2014-06-17", "2014-06-09", "2014-06-14","2014-07-01", "2014-08-04"), 
          competitor =c("amazon","apple","google","facebook","alibaba","tencent","ebay","bestbuy","gamespot","louis vuitton","gucci","tesla"), 
          competitor_price =c(2.5,2.35,1.99,2.01,2.22,2.52,5.32,5.56,5.01,6.01,5.86,5.96), stringsAsFactors=FALSE) 

competitor_data$crawl_date = as.Date(competitor_data$crawl_date) 
product_price <- data.frame(productId=c('banana', 'banana','banana', 'banana','banana', 'banana','fig', 'fig','fig', 'fig','fig', 'fig'), 
             date=c("2014-05-05", "2014-06-22", "2014-07-05", "2014-08-31","2014-05-03", "2014-02-22", 
                "2014-05-21", "2014-06-19", "2014-03-09", "2014-06-22","2014-07-03", "2014-09-08"), 
            price =c(2.12,2.31,2.29,2.01,2.04,2.09,5.22,5.36,5.21,5.91,5.36,5.56), stringsAsFactors=FALSE) 

product_price$date = as.Date(product_price$date) 

目的

  • 、各レコード(日)のために、competitor_dataから 関連crawl_date価格を見つけます。
  • product_price $の価格を最低のcompetitor_data $ competitor_priceと比較してください。
  • PRODUCT_PRICEの$価格< = competitor_data $ competitor_price場合は、フラグ1(price_leader)他のフラグを0(price_leader)に新しい列を作成

ループのネストされたを使用して、以下の私のスクリプトが、それはに24時間以上かかりますプロセス5000ユニークproduct_id:

unique_skus <- unique(product_price$productId) 
all_competitive_data <- data.frame() 
mid_step_data <- data.frame() 

start_time <-Sys.time() 
for (i in 1:length(unique_skus)){ 
    step1 <- subset(product_price, productId == unique_skus[i]) 
    transact_dates = unique(step1$date) 
    for (a in 1:length(transact_dates)){ 
    step2 <- subset(step1, date ==transact_dates[a]) 
    step3 <- inner_join(step2,competitor_data, by='productId') 
    if (nrow(subset(step3, date > crawl_date)) == 0){ 
     step3 <- step3[ order(step3$crawl_date , decreasing = FALSE),] 
     competitor_price <- head(step3,1)$competitor_price 
     step2$competitor_price = competitor_price 
    } 
    else { 
     step4 <- subset(step3, date > crawl_date) 
     step4 <- step4[ order(step4$crawl_date , decreasing = TRUE),] 
     competitor_price <- head(step4,1)$competitor_price 
     step2$competitor_price = competitor_price 
    } 
    step2$price_leader <- ifelse(step2$price <= step2$competitor_price, 1, 0) 
    mid_step_data = rbind(mid_step_data,step2) 
    } 
    all_competitive_data <- rbind(all_competitive_data,mid_step_data) 
} 
Sys.time()-start_time 
all_competitive_data = unique(all_competitive_data) 

dplyrを使用してこれを行う方法はありますか?

+0

crawl_dateは必ずしも日付にマッピングされていないため、なぜ2つの価格の列 – rawr

+0

を比較し、製品ID、日付ごとに二つのデータセットをマージしません。私のコードの文があるかどうか見てください。 – BlackHat

+0

あなたは次の最も近い日付の価格を選んでいるので、マージ後に最後の観測は繰り越し機能を使用してNAsを埋めます – rawr

答えて

3
competitor_data <- data.frame(productId=c('banana', 'banana','banana', 'banana','banana', 'banana','fig', 'fig','fig', 'fig','fig', 'fig'), 
           crawl_date=c("2014-04-05", "2014-04-22", "2014-05-05", "2014-05-22","2014-06-05", "2014-06-22", 
              "2014-05-08", "2014-06-17", "2014-06-09", "2014-06-14","2014-07-01", "2014-08-04"), 
           competitor =c("amazon","apple","google","facebook","alibaba","tencent","ebay","bestbuy","gamespot","louis vuitton","gucci","tesla"), 
           competitor_price =c(2.5,2.35,1.99,2.01,2.22,2.52,5.32,5.56,5.01,6.01,5.86,5.96), stringsAsFactors=FALSE) 

competitor_data$crawl_date = as.Date(competitor_data$crawl_date) 
# 
product_price <- data.frame(productId=c('banana', 'banana','banana', 'banana','banana', 'banana','fig', 'fig','fig', 'fig','fig', 'fig'), 
          date=c("2014-05-05", "2014-06-22", "2014-07-05", "2014-08-31","2014-05-03", "2014-02-22", 
            "2014-05-21", "2014-06-19", "2014-03-09", "2014-06-22","2014-07-03", "2014-09-08"), 
          price =c(2.12,2.31,2.29,2.01,2.04,2.09,5.22,5.36,5.21,5.91,5.36,5.56), stringsAsFactors=FALSE) 

product_price$date = as.Date(product_price$date) 

あるNASとのベクトルを埋めるために、この関数を使用して転送しますn逆方向

## fill in NAs 
f <- function(..., lead = NA) { 
    # f(NA, 1, NA, 2, NA, NA, lead = NULL) 
    x <- c(lead, c(...)) 
    head(zoo::na.locf(zoo::na.locf(x, na.rm = FALSE), fromLast = TRUE), 
     if (is.null(lead)) length(x) else -length(lead)) 
} 

2つを製品と日付で結合します。私たちは追加のNAで製品ごとに最初の価格を塗りつぶすので、これはNAsを記入するとき以前の価格を効果的に使用するでしょう

次に価格と競合他社価格の比較を行います。最後のステップは、単にいくつかは、それはあなたがこれらのdplyrするための手順やdata.table構文のいずれかを変更することができ、同じ結果

dd <- merge(product_price, competitor_data, 
      by.y = c('productId', 'crawl_date'), 
      by.x = c('productId', 'date'), all = TRUE) 
dd$competitor_price <- 
    unlist(sapply(split(dd$competitor_price, dd$productId), f)) 
dd$price_leader <- +(dd$price <= dd$competitor_price) 
(res1 <- `rownames<-`(dd[!is.na(dd$price_leader), -4], NULL)) 

# productId  date price competitor_price price_leader 
# 1  banana 2014-02-22 2.09    2.50   1 
# 2  banana 2014-05-03 2.04    2.35   1 
# 3  banana 2014-05-05 2.12    2.35   1 
# 4  banana 2014-06-22 2.31    2.22   0 
# 5  banana 2014-07-05 2.29    2.52   1 
# 6  banana 2014-08-31 2.01    2.52   1 
# 7  fig 2014-03-09 5.21    5.32   1 
# 8  fig 2014-05-21 5.22    5.32   1 
# 9  fig 2014-06-19 5.36    5.56   1 
# 10  fig 2014-06-22 5.91    5.56   0 
# 11  fig 2014-07-03 5.36    5.86   1 
# 12  fig 2014-09-08 5.56    5.96   1 

res0 <- `rownames<-`(all_competitive_data[ 
    order(all_competitive_data$productId, all_competitive_data$date), ], NULL) 

all.equal(res0, res1) 
# [1] TRUE 

であることを証明するためにクリーンアップされます。私は1つのいずれかを使用していないが、それはストレートフォワードする必要があります:

library('dplyr') 
dd <- full_join(product_price, competitor_data, 
       by = c(
        'productId' = 'productId', 
        'date' = 'crawl_date' 
       ) 
) %>% arrange(productId, date) 

dd %>% group_by(productId) %>% 
    mutate(
    competitor_price = f(competitor_price), 
    price_leader = as.integer(price <= competitor_price) 
) %>% filter(!is.na(price_leader)) %>% select(-competitor) 

# Source: local data frame [12 x 5] 
# Groups: productId [2] 
# 
#  productId  date price competitor_price price_leader 
#   <chr>  <date> <dbl>   <dbl>  <int> 
# 1  banana 2014-02-22 2.09    2.50   1 
# 2  banana 2014-05-03 2.04    2.35   1 
# 3  banana 2014-05-05 2.12    2.35   1 
# 4  banana 2014-06-22 2.31    2.22   0 
# 5  banana 2014-07-05 2.29    2.52   1 
# 6  banana 2014-08-31 2.01    2.52   1 
# 7  fig 2014-03-09 5.21    5.32   1 
# 8  fig 2014-05-21 5.22    5.32   1 
# 9  fig 2014-06-19 5.36    5.56   1 
# 10  fig 2014-06-22 5.91    5.56   0 
# 11  fig 2014-07-03 5.36    5.86   1 
# 12  fig 2014-09-08 5.56    5.96   1 
0

以下の解決策では、dplyr joinを使用して一致させています。 (注:そのdplyrが参加するので、私は「日」に「crawl_date」に変更が自動的に一致する列を選択することになるそれは参加するパラメータとして

by=c('productId'='productId', date'='crawl_date') 

のようなものを使用して明示的に一致させることができる

competitor_data <- data.frame(productId=c('banana', 'banana','banana', 'banana','banana', 'banana','fig', 'fig','fig', 'fig','fig', 'fig'), 
           date=c("2014-04-05", "2014-04-22", "2014-05-05", "2014-05-22","2014-06-05", "2014-06-22", 
              "2014-05-08", "2014-06-17", "2014-06-09", "2014-06-14","2014-07-01", "2014-08-04"), 
           competitor =c("amazon","apple","google","facebook","alibaba","tencent","ebay","bestbuy","ga**strong text**mespot","louis vuitton","gucci","tesla"), 
           competitor_price =c(2.5,2.35,1.99,2.01,2.22,2.52,5.32,5.56,5.01,6.01,5.86,5.96), stringsAsFactors=FALSE) 

competitor_data$date = as.Date(competitor_data$date) 

product_price <- data.frame(productId=c('banana', 'banana','banana', 'banana','banana', 'banana','fig', 'fig','fig', 'fig','fig', 'fig'), 
          date=c("2014-05-05", "2014-06-22", "2014-07-05", "2014-08-31","2014-05-03", "2014-02-22", 
            "2014-05-21", "2014-06-19", "2014-03-09", "2014-06-22","2014-07-03", "2014-09-08"), 
          price =c(2.12,2.31,2.29,2.01,2.04,2.09,5.22,5.36,5.21,5.91,5.36,5.56), stringsAsFactors=FALSE) 

product_price$date = as.Date(product_price$date) 

require(dplyr) 
joined <- product_price %>% left_join(competitor_data) 
joined$leader <- as.integer(joined$price <= joined$competitor_price) 

joined 

得られたデータフレームが

productId  date price competitor competitor_price leader 
1  banana 2014-05-05 2.12  google    1.99  0 
2  banana 2014-06-22 2.31 tencent    2.52  1 
3  banana 2014-07-05 2.29  <NA>    NA  NA 
4  banana 2014-08-31 2.01  <NA>    NA  NA 
5  banana 2014-05-03 2.04  <NA>    NA  NA 
6  banana 2014-02-22 2.09  <NA>    NA  NA 
7  fig 2014-05-21 5.22  <NA>    NA  NA 
8  fig 2014-06-19 5.36  <NA>    NA  NA 
9  fig 2014-03-09 5.21  <NA>    NA  NA 
10  fig 2014-06-22 5.91  <NA>    NA  NA 
11  fig 2014-07-03 5.36  <NA>    NA  NA 
12  fig 2014-09-08 5.56  <NA>    NA  NA 
> 
+0

これは私のif文です。 dateとcrawl_dateは必ずしも同じではありません。特定の日付の場合、最も近いcrawl_date(crawl_date before)を使用します。私のif文を見てください。私は論理を入れた。 – BlackHat