valori di sottrazione in base a una variabile che inizia con 'c da un set di dati transazionaleCiao, ho un dataframe con una colonna chiamata "InvoiceNumber" (fatturaNo, esempio 541.431 ). E un'altra colonna chiamata 'Stockcode'.
Quando InvoiceNo inizia con una C (esempio C541433 ) e corrisponde a un codice di scorta precedente Devo cancellare la 'Quantità' e / o 'Prezzo unitario' dalla mia analisi . (significa che un cliente HA RESTITUITO l'articolo). Sto provando a fare un'analisi RFM e un'analisi del mercato, ma prima devo tenerne conto prima. Come posso sottrarre il totale speso per ID cliente in Quantità e prezzo unitario quando restituiscono un articolo (e ho una riga con un Invoiceno che inizia con "C".
Come posso risolvere questo problema? Ho 500K + righe di dati transazionali.
| Fattura n | Codice magazzino | Descrizione | Quantità | Data fattura | Prezzo unitario | Identificativo del cliente | Nazione |
| 541.431 | 23166 | BARATTOLO SUPERIORE MEDIO IN CERAMICA | 74215 | 18/1/2011 10:01 | 1.04 | 12346 | Regno Unito |
| C541433 | 23166 | BARATTOLO SUPERIORE MEDIO IN CERAMICA | -74.215 | 18/1/2011 10:17 | 1.04 | 12346 | Regno Unito |
| 537.626 | 85.116 | PORTA T-LIGHT NERO CANDELABRA | 12 | 7/12/2010 14:57 | 2.1 | 12347 | Islanda |
| 537.626 | 22375 | SACCA AIRLINI VINTAGE JET SET MARRONE | 4 | 7/12/2010 14:57 | 4.25 | 12347 | Islanda |
| 537.626 | 71.477 | VETRO COLORE. PORTA T-LIGHT STAR | 12 | 7/12/2010 14:57 | 3.25 | 12347 | Islanda |
| 537.626 | 22492 | MINI PAINT SET VINTAGE | 36 | 7/12/2010 14:57 | 0.65 | 12347 | Islanda |
| 537.626 | 22771 | PULIZIA DELLA CASSETTA DEL CASSETTO ACRYLIC EDWARDIAN | 12 | 7/12/2010 14:57 | 1.25 | 12347 | Islanda |
| 537.626 | 22772 | PISTOLA CASSETTO ROSA ACRILICO EDWARDIANO | 12 | 7/12/2010 14:57 | 1.25 | 12347 | Islanda |
| 537.626 | 22773 | MANOPOLA CASSETTO VERDE ACRILICO EDWARDIANO | 12 | 7/12/2010 14:57 | 1.25 | 12347 | Islanda |
| 537.626 | 22774 | MANIGLIA DEL CASSETTO ROSSO ACRILICO EDWARDIANO | 12 | 7/12/2010 14:57 | 1.25 | 12347 | Islanda |
| 537.626 | 22775 | DISEGNO VIOLA ACRILICO EDWARDIANO | 12 | 7/12/2010 14:57 | 1.25 | 12347 | Islanda |
| 537.626 | 22805 | MANIGLIA A CASSETTO BLU ACRILICO EDWARDIANO | 12 | 7/12/2010 14:57 | 1.25 | 12347 | Islanda |
| 537.626 | 22725 | CIOCCOLATO ALARM CLOCK BAKELIKE | 4 | 7/12/2010 14:57 | 3.75 | 12347 | Islanda |
| 537.626 | 22726 | OROLOGIO SVEGLIA BAKELIKE VERDE | 4 | 7/12/2010 14:57 | 3.75 | 12347 | Islanda |
| 537.626 | 22727 | OROLOGIO SVEGLIA BAKELIKE ROSSO | 4 | 7/12/2010 14:57 | 3.75 | 12347 | Islanda |
| 537.626 | 22728 | OROLOGIO SVEGLIA BAKELIKE ROSA | 4 | 7/12/2010 14:57 | 3.75 | 12347 | Islanda |
| 537.626 | 22729 | OROLOGIO SVEGLIA BAKELIKE ARANCIA | 4 | 7/12/2010 14:57 | 3.75 | 12347 | Islanda |
Ri: i valori di sottrazione dipendono da una variabile che inizia con 'c da un set di dati transazionaliDi seguito è una nuova versione che riconcilia completamente i dati in un singolo passaggio della tabella di dati. Ci vogliono circa 30 secondi per l'elaborazione
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" );
Ri: i valori di sottrazione dipendono da una variabile che inizia con 'c da un set di dati transazionaliGrazie Kevin! sì, includerei che 1 "sinistra" nella contabilità
@Kevin_Anderson ha scritto:
Ciao, Alexllorens!
È qualcosa che fai una volta o qualcosa che fai ripetutamente? Presumo che la risposta sia "ripetutamente". Se è così, dovresti scrivere uno script JSL.
È possibile che un cliente restituisca meno di un ordine completo? In altre parole, se un cliente ha ordinato 50 unità e restituito 49, vorresti includere l'1 resto nella contabilità?
Ri: i valori di sottrazione dipendono da una variabile che inizia con 'c da un set di dati transazionaliNon ho compreso appieno tutte le sfumature, in particolare ciò che costituisce la chiave primaria composta per identificare i record da regolare, né quali modifiche dovrebbero essere apportate.
Ma potrebbe essere che uno sviluppo del codice qui sotto potrebbe farlo. Non un confronto equo, ma ci vuole meno di un secondo per fare quello che fa:
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);
Ri: i valori di sottrazione dipendono da una variabile che inizia con 'c da un set di dati transazionaliDi seguito uno script che prende i record di UnBooking e rimuove la loro quantità di UnBooking dal record di prenotazione precedente per il dato StockCode. Quindi imposta la quantità di UnBooking su zero. Se non viene trovato alcun record di prenotazione precedente, si presume che il record esistesse prima dell'inizio di questa tabella di dati e imposta la quantità di UnBooking su zero.
Il problema con questo script è che non è molto efficiente. Su oltre 54.000 dischi, il mio vecchio sistema impiegava 55 minuti. Potrebbero essere utilizzate altre metodologie che aumenterebbero la velocità, ma ho cercato di sviluppare qualcosa che seguisse la tua metodologia implicita.
Lo script è anche incompleto nel trattare pienamente la riconciliazione dei dati. Cioè, se la quantità di UnBooking è 10 (nei dati, -10) e la quantità di Prenotazione precedente è 7, lo script non accetta i 3 prodotti non riconciliati e continua indietro per trovare il successivo record di prenotazione e sottrarre i 3 prodotti non concessi da quella prenotazione. Questo potrebbe essere aggiunto se si sceglie di implementare il mio metodo.
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" );
Ri: i valori di sottrazione dipendono da una variabile che inizia con 'c da un set di dati transazionaliCiao, Alexllorens!
È qualcosa che fai una volta o qualcosa che fai ripetutamente? Presumo che la risposta sia "ripetutamente". Se è così, dovresti scrivere uno script JSL.
È possibile che un cliente restituisca meno di un ordine completo? In altre parole, se un cliente ha ordinato 50 unità e restituito 49, vorresti includere l'1 resto nella contabilità?