트랜잭션 데이터 세트에서 'c'로 시작하는 변수에 따라 값을 빼기안녕하세요, 저는 'InvoiceNumber'라는 이름의 열이있는 데이터 프레임을 가지고 있습니다 (invoiceNo, example 541431 ). 'Stockcode'라는 또 다른 열.
InvoiceNo가 C로 시작하면 (예 C541433 ) 이전 StockCode와 일치합니다 내 분석에서 '수량'및 / 또는 '단위 가격'을 취소해야합니다. . (고객이 상품을 반품했음을 의미합니다). 나는 RFM 분석과 Market Basket Analysis를 시도하고있다. 그러나 먼저 이것을 고려해야한다. 항목을 반환 할 때 수량 및 단위 가격 모두에서 CustomerID 당 소비 한 총액을 어떻게 뺄수 있습니까? (그리고 'C'로 시작하는 Invoiceno 행이 있습니다.)
이 문제를 어떻게 해결할 수 있습니까? 500K + 행의 트랜잭션 데이터가 있습니다.
| 인보이스 없음 | StockCode | 기술 | 수량 | 송장 날짜 | 단가 | 고객 ID | 국가 |
| 541431 | 23166 | 중 세라믹 최고 저장 용기 | 74215 | 2011 년 1 월 18 일 10:01 | 1.04 | 12346 | 영국 |
| C541433 | 23166 | 중 세라믹 최고 저장 용기 | -74215 | 18/1/2011 10:17 | 1.04 | 12346 | 영국 |
| 537626 | 85116 | BLACK CANDELABRA T-LIGHT HOLDER | 12 | 2010 년 7 월 12 일 14:57 | 2.1 | 12347 | 아이슬란드 |
| 537626 | 22375 | AIRLINE BAG VINTAGE JET SET BROWN | 4 | 2010 년 7 월 12 일 14:57 | 4.25 | 12347 | 아이슬란드 |
| 537626 | 71477 | 색깔 유리. STAR T-LIGHT HOLDER | 12 | 2010 년 7 월 12 일 14:57 | 3.25 | 12347 | 아이슬란드 |
| 537626 | 22492 | MINI PAINT SET VINTAGE | 36 | 2010 년 7 월 12 일 14:57 | 0.65 | 12347 | 아이슬란드 |
| 537626 | 22771 | 서랍 노브 아크릴 에드윈을 지우십시오. | 12 | 2010 년 7 월 12 일 14:57 | 1.25 | 12347 | 아이슬란드 |
| 537626 | 22772 | 핑크색 서랍 주임 아크릴릭 에드워즈 | 12 | 2010 년 7 월 12 일 14:57 | 1.25 | 12347 | 아이슬란드 |
| 537626 | 22773 | 녹색 서랍 손목 아크릴 에드워즈 | 12 | 2010 년 7 월 12 일 14:57 | 1.25 | 12347 | 아이슬란드 |
| 537626 | 22774 | 빨간 서랍 손목 아크릴 에드워드 디올 | 12 | 2010 년 7 월 12 일 14:57 | 1.25 | 12347 | 아이슬란드 |
| 537626 | 22775 | 보라색 드와 르크 손 아크릴릭 EDWARDIAN | 12 | 2010 년 7 월 12 일 14:57 | 1.25 | 12347 | 아이슬란드 |
| 537626 | 22805 | 파란색 서랍 목덜미 아크릴릭 EDWARDIAN | 12 | 2010 년 7 월 12 일 14:57 | 1.25 | 12347 | 아이슬란드 |
| 537626 | 22725 | 알람 시계 빵집 초콜릿 | 4 | 2010 년 7 월 12 일 14:57 | 3.75 | 12347 | 아이슬란드 |
| 537626 | 22726 | 알람 시계 파킹 그린 | 4 | 2010 년 7 월 12 일 14:57 | 3.75 | 12347 | 아이슬란드 |
| 537626 | 22727 | ALARM CLOCK BAKELIKE RED | 4 | 2010 년 7 월 12 일 14:57 | 3.75 | 12347 | 아이슬란드 |
| 537626 | 22728 | 알람 시계 바클리크 핑크 | 4 | 2010 년 7 월 12 일 14:57 | 3.75 | 12347 | 아이슬란드 |
| 537626 | 22729 | 알람 시계 주황색 주황색 | 4 | 2010 년 7 월 12 일 14:57 | 3.75 | 12347 | 아이슬란드 |
다시 : 트랜잭션 데이터 집합에서 시작하는 변수에 따라 값을 빼기아래는 데이터 테이블의 단일 단계에서 데이터를 완전히 조정하는 새 버전입니다. 처리하는 데 약 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" );
다시 : 트랜잭션 데이터 집합에서 시작하는 변수에 따라 값을 빼기케빈 감사합니다! 예, 나는 회계에 '좌익'을 포함 시켰습니다.
@Kevin_Anderson 쓴 :
안녕, Alexllorens!
이것은 당신이 한 번하는 일입니까, 아니면 반복적으로하는 일입니까? 대답은 "반복적으로"있다고 가정합니다. 그렇다면 JSL 스크립트를 작성해야합니다.
고객이 전체 주문보다 적은 금액을 반환 할 수 있습니까? 즉, 고객이 50 개 단위를 주문하고 49 개를 반환하면 회계에 1 잔여분을 포함 시키시겠습니까?
다시 : 트랜잭션 데이터 집합에서 시작하는 변수에 따라 값을 빼기필자는 모든 뉘앙스, 특히 조정해야 할 레코드를 식별하기 위해 합성 기본 키를 사용하는 것이 무엇인지, 어떤 조정이 이루어져야 하는지를 완전히 이해하지 못했습니다.
그러나 아래의 코드를 개발할 수 있습니다. 공평한 비교는 아니지만 그것이하는 일을하는 데는 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);
다시 : 트랜잭션 데이터 집합에서 시작하는 변수에 따라 값을 빼기아래는 UnBooking 레코드를 가져 와서 해당 StockCode의 이전 예약 레코드에서 UnBooking 수량을 제거하는 스크립트입니다. 그런 다음 UnBooking 수량을 0으로 설정합니다. 이전 예약 레코드가 발견되지 않으면, 레코드가이 데이터 테이블의 시작 전에 존재했다고 가정하고 UnBooking의 수량을 0으로 설정합니다.
이 스크립트의 문제점은 매우 효율적이지 않다는 것입니다. 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" );
다시 : 트랜잭션 데이터 집합에서 시작하는 변수에 따라 값을 빼기안녕, Alexllorens!
이것은 당신이 한 번하는 일입니까, 아니면 반복적으로하는 일입니까? 대답은 "반복적으로"있다고 가정합니다. 그렇다면 JSL 스크립트를 작성해야합니다.
고객이 전체 주문보다 적은 금액을 반환 할 수 있습니까? 즉, 고객이 50 개 단위를 주문하고 49 개를 반환하면 회계에 1 잔여분을 포함 시키시겠습니까?