トランザクションデータセットから 'c'で始まる変数に応じて値を減算するこんにちは、'InvoiceNumber'という名前の列を持つデータフレームがあります(invoiceNo、例 541431 ) そして別の列に「Stockcode」という名前が付けられています。
InvoiceNoがCで始まる場合(例 C541433 そして、それは前のStockCodeと一致します分析から「数量」または「単価」をキャンセルする必要があります 。(顧客が商品を返品したことを意味します)。RFM分析とマーケットバスケット分析を実行しようとしていますが、まず最初にこれを考慮する必要があります。どのようにして数量と単価の両方でCustomerIDごとに消費された合計金額を差し引くことができますか(そして 'C'で始まるInvoicenoの行があります)。
どのように私はこの問題を解決することができますか?トランザクションデータが500K行以上あります。
| 請求書番号 | 自社コード | 説明 | 量 | 請求書の日付 | 単価 | 顧客ID | 国 |
| 541431 | 23166 | ミディアムセラミックトップストレージJAR | 74215 | 2011年1月18日10時01分 | 1.04 | 12346 | イギリス |
| C541433 | 23166 | ミディアムセラミックトップストレージJAR | -74215 | 2011年1月18日10時17分 | 1.04 | 12346 | イギリス |
| 537626 | 85116 | ブラックキャンデラブラT-ライトホルダー | 12年 | 7/12/2010 14:57 | 2.1 | 12347 | アイスランド |
| 537626 | 22375 | エアラインバッグヴィンテージジェットセットブラウン | 4 | 7/12/2010 14:57 | 4.25 | 12347 | アイスランド |
| 537626 | 71477 | COLOR GLASS。スターT-ライトホルダー | 12年 | 7/12/2010 14:57 | 3.25 | 12347 | アイスランド |
| 537626 | 22492 | ミニペイントセットヴィンテージ | 36 | 7/12/2010 14:57 | 0.65 | 12347 | アイスランド |
| 537626 | 22771 | クリアドローアーノブアクリルエドワード | 12年 | 7/12/2010 14:57 | 1.25 | 12347 | アイスランド |
| 537626 | 22772 | PINK DRAWERノブアクリルエドワード | 12年 | 7/12/2010 14:57 | 1.25 | 12347 | アイスランド |
| 537626 | 22773 | グリーン引き出しノブアクリルエドワード | 12年 | 7/12/2010 14:57 | 1.25 | 12347 | アイスランド |
| 537626 | 22774 | 赤い引き出しノブアクリルエドワード | 12年 | 7/12/2010 14:57 | 1.25 | 12347 | アイスランド |
| 537626 | 22775 | パープルドローイングノブアクリルエドワード | 12年 | 7/12/2010 14:57 | 1.25 | 12347 | アイスランド |
| 537626 | 22805 | ブルー引き出しノブアクリルエドワード | 12年 | 7/12/2010 14:57 | 1.25 | 12347 | アイスランド |
| 537626 | 22725 | アラームクロックベークライクチョコレート | 4 | 7/12/2010 14:57 | 3.75 | 12347 | アイスランド |
| 537626 | 22726 | アラームクロックベークライクグリーン | 4 | 7/12/2010 14:57 | 3.75 | 12347 | アイスランド |
| 537626 | 22727 | アラームクロックベークライクレッド | 4 | 7/12/2010 14:57 | 3.75 | 12347 | アイスランド |
| 537626 | 22728 | アラームクロックベークライクピンク | 4 | 7/12/2010 14:57 | 3.75 | 12347 | アイスランド |
| 537626 | 22729 | アラームクロックベークライクオレンジ | 4 | 7/12/2010 14:57 | 3.75 | 12347 | アイスランド |
トランザクションデータセットから 'c'で始まる変数に応じて値を減算する以下は、データテーブルの1回のパスでデータを完全に調整する新しいバージョンです。 処理には約30秒かかります
Names Default To Here( 1 );
dt = Current Data Table();
// Add a RowNum column to permit the reordering back to
// the original order after processing
dt << New Column( "RowNum", formula( Row() ) );
dt:RowNum << delete property( "formula" );
// Sort the data so that processing can start at the
// top of the data, and flow downward, and the required
// data are grouped together and in row order
dt << Sort(
By( :CustomerID, :StockCode, :RowNum ),
Order( Ascending, Ascending, Descending ),
Replace Table( 1 )
);
// Find the starting row, that is, the first row with a
// CustomerID value
Start = 1;
While( Is Missing( dt:CustomerID[Start] ) == 1, Start++ );
// Loop across all rows, starting with the first non missing
// CustomerID
For( RowCNT = Start, RowCNT <= N Rows( dt ), RowCNT++,
// When the CustomerID or StockCode changes, or if this is
// the first loop, zero out the UnBookingAmount
If(
Try( :CustomerID[RowCNT - 1], "" ) != :CustomerID[RowCNT] |
Try( :StockCode[RowCNT - 1], "" ) != :StockCode[RowCNT] | RowCNT == Start,
UnBookingAmount = 0
);
// If this is a Change Invoice, then add the change to
// the running UnBookingAmount (Summing a negative amount actually makes
// the value of UnBookingAmount even more negative)
If( Starts With( :InvoiceNo[RowCNT], "C" ) == 1,
UnBookingAmount = Sum( UnBookingAmount, :Quantity[RowCNT] );
:Quantity[RowCNT] = 0;
, // Else
// Reduct the order by the current value of UnBookingAmount
:Quantity[RowCNT] = Sum( UnBookingAmount, :Quantity[RowCNT] );
// If the Quantity is less than zero, that means more
// UnBooking amount needs to be subtracted on earlier
// orders so reset the UnBookingAmountt remaining to be reconciled,
// and set the current order to 0
If( :Quantity[RowCNT] < 0,
UnBookingAmount = :Quantity[RowCNT];
:Quantity[RowCNT] = 0;
, // Else
// If the Quantity is >= 0 that means all UnBookings
// have been handled, so set the UnBookingAmount to 0
UnBookingAmount = 0
);
);
);
// Reorder the table back to the original order
dt << Sort( By( :RowNum ), Order( Ascending ), Replace Table( 1 ) );
// Delete the no longer needed RowNum column
dt << delete columns( "RowNum" );
トランザクションデータセットから 'c'で始まる変数に応じて値を減算するありがとうケビン!はい、私はその1を「会計」に含めます
@Kevin_Anderson 書きました:
こんにちは、Alexllorensです!
これはあなたがかつてやることなのか、それとも何度も何度もすることですか。答えは「繰り返し」だと思います。 もしそうなら、あなたはJSLスクリプトを書くべきです。
顧客が全注文より少なく返品することは可能ですか?つまり、顧客が50個注文して49個返品した場合、残りの1を会計に含めますか?
トランザクションデータセットから 'c'で始まる変数に応じて値を減算する私はすべての微妙な違い、特に調整すべきレコードを識別するための複合主キーが何を意味するのか、またどのような調整を行うべきかを完全には理解していませんでした。
しかし、それは以下のコードの開発がそれをすることができるということかもしれません。公平な比較ではありませんが、実行する処理に1秒もかかりません。
NamesDefaultToHere(1);
dt = DataTable("Original");
// Find and select all the rows for a cancelled transaction
dt << selectWhere(startsWith(:InvoiceNo, "C"));
// Put these transactions into another table
dt2 = dt << Subset(SelectedRows(1), Columns(:Stock Code, :Customer ID, :UnitPrice));
dt2 << setName("Cancelled");
// Delete the cancelled transactions in dt
dt << deleteRows;
// Join dt2 to dt
dt3 = dt << Join(
With( dt2 ),
By Matching Columns(
:StockCode = :StockCode,
:CustomerID = :CustomerID,
:UnitPrice = :UnitPrice
),
Drop multiples( 0, 0 ),
Include Nonmatches( 1, 0 ),
Preserve main table order( 1 ),
OutputTableName("Work with Me")
);
Close(dt, NoSave);
Close(dt2, NoSave);
トランザクションデータセットから 'c'で始まる変数に応じて値を減算する以下は、UnBookingレコードを取得し、特定のStockCodeの前の予約レコードからそれらのUnBooking数量を削除するスクリプトです。 次に、UnBooking数量をゼロに設定します。 以前の予約レコードが見つからない場合は、このデータテーブルの開始前にレコードが存在していたと見なされ、UnBookingの数量がゼロに設定されます。
このスクリプトの問題は、それがあまり効率的ではないということです。 54,000以上のレコードで、私の古いシステムに55分かかりました。 速度を上げるために他の方法論を使用することもできますが、私はあなたの暗黙の方法論に従う何かを開発することに努めました。
スクリプトは、データの調整を完全に処理することにおいても不完全です。 つまり、UnBooking数量が10(データでは-10)で、前の予約数量が7の場合、スクリプトは未調整の3つの商品を受け取らずに次の予約レコードを見つけるために逆方向に進み、3つの未調整の商品を差し引きます。その予約から。 あなたが私の方法論を実行することを選択した場合、それは追加されるかもしれません。
Names Default To Here( 1 );
dt = Current Data Table();
// Record the starting time to allow the reporting of the amount of time it takes to
// perform all of the calculations
start = Today();
// Create a new column that represents the row number in the data table
dt << New Column( "RowNum", formula( Row() ) );
dt:RowNum << delete Property( "Formula" );
// Find all of the observations in the data table that are UnBookings
UnBookList = dt << get rows where( Uppercase( Left( :InvoiceNo, 1 ) ) == "C" & :Quantity < 0 );
// Loop across all of the UnBookings and subtract the UnBooking quantity from the
// Booking order record
For( corrections = 1, corrections <= N Rows( UnBookList ), corrections++,
// Print out the processing progress
If( Mod( corrections, 100 ) == 0,
time = Format( Today() - start, "hr:m:s" );
Show( time );
);
// Get the values of specific values for the current row being processed
curRowNum = UnBookList[corrections];
curCustomerID = dt:CustomerID[curRowNum];
curStockCode = dt:StockCode[curRowNum];
// Find the last row from the CustomerID's order for the StockCode being UnBooked
last row = Max( dt << get rows where( :quantity > 0 & curCustomerID == :CustomerID & curStockCode == :StockCode & :RowNum < curRowNum ) );
// If the record was found, then subtract (Sum the negative quantity) from the ordered quantity.
// Also, set the current rows quantity to zero
If( Is Missing( Last row ) == 0,
dt:Quantity[Last row] = Sum( dt:Quantity[Last row], dt:Quantity[curRowNum] );
);
// Set the current row's quantity value to zero
dt:Quantity[curRowNum] = 0;
);
// Print out the results
Show( N Rows( dt << get rows where( :quantity < 0 & Uppercase( Left( :InvoiceNo, 1 ) ) == "C" ) ) );
// Show the time it took to process the file
time = Format( Today() - start, "hr:m:s" );
Show( time );
// Delete the utility column RowNum
dt << Delete Columns( "RowNum" );
トランザクションデータセットから 'c'で始まる変数に応じて値を減算するこんにちは、Alexllorensです!
これはあなたがかつてやることなのか、それとも何度も何度もすることですか。答えは「繰り返し」だと思います。 もしそうなら、あなたはJSLスクリプトを書くべきです。
顧客が全注文より少なく返品することは可能ですか?つまり、顧客が50個注文して49個返品した場合、残りの1を会計に含めますか?