我正在處理的交易數據來自兩個來源,兩者都有一些優點和缺點。第一個只有有準確的$和出售單位(DF_Lookup
),第二個有正確的人口統計(DFI
),但某些售出的單位和單位不正確。所以,我寫了下面的代碼來處理這個問題。使用R更正/整理數據
這裏是我的數據:
DFI
dput(DFI)
structure(list(PO_ID = c("P1234", "P1234", "P1234", "P1234",
"P1234", "P1234", "P2345", "P2345", "P3456", "P4567"), SO_ID = c("S1",
"S1", "S1", "S2", "S2", "S2", "S3", "S4", "S7", "S10"), F_Year = c(2012,
2012, 2012, 2013, 2013, 2013, 2011, 2011, 2014, 2015), Product_ID = c("385X",
"385X", "385X", "450X", "450X", "900X", "3700", "3700", "A11U",
"2700"), Revenue = c(1, 2, 3, 34, 34, 6, 7, 88, 9, 100), Quantity = c(1,
2, 3, 8, 8, 6, 7, 8, 9, 40), Location1 = c("MA", "NY", "WA",
"NY", "WA", "NY", "IL", "IL", "MN", "CA")), .Names = c("PO_ID",
"SO_ID", "F_Year", "Product_ID", "Revenue", "Quantity", "Location1"
), row.names = c(NA, 10L), class = "data.frame")
DF_Lookup
dput(DF_Lookup)
structure(list(PO_ID = c("P1234", "P1234", "P1234", "P2345",
"P2345", "P3456", "P4567"), SO_ID = c("S1", "S2", "S2", "S3",
"S4", "S7", "S10"), F_Year = c(2012, 2013, 2013, 2011, 2011,
2014, 2015), Product_ID = c("385X", "450X", "900X", "3700", "3700",
"A11U", "2700"), Revenue = c(50, 70, 35, 100, -50, 50, 100),
Quantity = c(3, 20, 20, 20, -10, 20, 40)), .Names = c("PO_ID",
"SO_ID", "F_Year", "Product_ID", "Revenue", "Quantity"), row.names = c(NA,
7L), class = "data.frame")
的第一次嘗試:
策略: - 使用加入覆蓋從DF_Lookup
的條目DFI
DF_Generated <- DFI %>%
left_join(DF_Lookup,by = c("PO_ID", "SO_ID", "F_Year", "Product_ID")) %>%
dplyr::group_by(PO_ID, SO_ID, F_Year, Product_ID) %>%
dplyr::mutate(Count = n()) %>%
dplyr::ungroup()%>%
dplyr::mutate(Revenue = Revenue.y/Count, Quantity = Quantity.y/Count) %>%
dplyr::select(PO_ID:Product_ID,Location1,Revenue,Quantity)
預期輸出:
dput(DF_Generated)
structure(list(PO_ID = c("P1234", "P1234", "P1234", "P1234",
"P1234", "P1234", "P2345", "P2345", "P3456", "P4567"), SO_ID = c("S1",
"S1", "S1", "S2", "S2", "S2", "S3", "S4", "S7", "S10"), F_Year = c(2012,
2012, 2012, 2013, 2013, 2013, 2011, 2011, 2014, 2015), Product_ID = c("385X",
"385X", "385X", "450X", "450X", "900X", "3700", "3700", "A11U",
"2700"), Location1 = c("MA", "NY", "WA", "NY", "WA", "NY", "IL",
"IL", "MN", "CA"), Revenue = c(16.6666666666667, 16.6666666666667,
16.6666666666667, 35, 35, 35, 100, -50, 50, 100), Quantity = c(1,
1, 1, 10, 10, 20, 20, -10, 20, 40)), class = c("tbl_df", "tbl",
"data.frame"), row.names = c(NA, -10L), .Names = c("PO_ID", "SO_ID",
"F_Year", "Product_ID", "Location1", "Revenue", "Quantity"))
挑戰:這非常適用於較小的數據集。我正在處理的原始數據有大約90萬條記錄。所以,上面的代碼需要永遠。
第二次嘗試: 因此,我認爲只更新那些有$ 和+/- 10%的範圍之外單位行。
這裏是我的代碼:
#Find out whether the numbers are within +/-10% range.
DF_Mod<-DFI %>%
dplyr::group_by(PO_ID, SO_ID, F_Year, Product_ID) %>%
dplyr::summarise(Rev_agg = sum(Revenue), Qty_agg = sum(Quantity)) %>%
left_join(DF_Lookup) %>%
dplyr::rowwise() %>%
#check for +/- 10% confidence interval
dplyr::mutate(Compute = ifelse((abs(Rev_agg-Revenue)/Revenue <=0.1) & (abs(Qty_agg-Quantity)/Quantity <=0.1),"N","Y")) %>%
dplyr::rowwise() %>%
dplyr::ungroup() %>%
dplyr::select(PO_ID:Product_ID,Compute) %>%
dplyr::right_join(DFI)
#Now, filter Compute == "Y" and then do the join with DF_Lookup.
DF_Generated_2 <- DF_Mod %>%
dplyr::filter(Compute == "Y") %>%
left_join(DF_Lookup,by = c("PO_ID", "SO_ID", "F_Year", "Product_ID")) %>%
dplyr::group_by(PO_ID, SO_ID, F_Year, Product_ID) %>%
dplyr::mutate(Count = n()) %>%
dplyr::ungroup()%>%
dplyr::mutate(Revenue = Revenue.y/Count, Quantity = Quantity.y/Count) %>%
dplyr::select(PO_ID:Product_ID,Location1,Revenue,Quantity)
#Bind the rows
DF_Final <- rbind(DF_Generated_2,DFI[DF_Mod$Compute=="N",]) #Expected output
這裏,DF_Final
確實是預期輸出。
問題:即使在遵循上述方法之後,由於涉及的連接數太多,性能非常緩慢。無論如何,我們可以加快這個過程嗎?還有其他更好的方法來做我想做的事嗎?
我很感激你的想法。我在這方面花了一天時間,但仍然無處可去。我很困難。
你有沒有嘗試加入其他軟件包的功能? http://stackoverflow.com/questions/4322219/whats-the-fastest-way-to-merge-join-data-frames-in-r – coletl
@coletl - 謝謝。我不太熟悉使用'data.table'和'sqldf'進行連接。如果有人能指導我,那真的會對我有幫助。 – watchtower