Ciao, ho la seguente sfida con la quale ho problemi con lo scripting.
La mia tabella dei dati di partenza è simile alla seguente. Vorrei moltiplicare Xi all'indietro partendo da col2 =0 come criterio e inserire i nuovi valori in una nuova colonna.
col1 col2
X1 0
X2y2
X3 y3
…
Xn yn
XX1 0
XX2 aa2
….
XXn yyn
….
….
La mia tabella dei dati finali sarebbe simile a questa:
col1 col2 col3
X1 0 Xn*Xn-1*……X3*X2*X1
X2 y2 Xn*Xn-1*…..X3*X2
X3 y3 Xn*Xn-1*….*X3
…
Xn e Xn
XX1 0 XXn*XXn-1*…..XX2*XX1
XX2 yy2 XXn*XXn-1*…..XX2
….
XXn yyn XXn
….
….
Qualcuno può aiutare? Davvero apprezzato!
I calcoli che vuoi sono molto facili da fare se i dati sono invertiti, quindi ecco un piccolo script che calcolerà i valori usando quell'idea
names default to here(1);
// create the sample table
dt = New Table( "example",
Add Rows( 10 ),
New Column( "col1",
Numeric,
"Continuous",
Format( "Best", 12 ),
Set Values( [1, 2, 3, 2, 4, 5, 6, 7, 8, 9] ),
Set Display Width( 48 )
),
New Column( "col2",
Character( 1 ),
"Nominal",
Set Values( {"x", "x", "x", "y", "y", "y", "y", "z", "z", "z"} ),
Set Display Width( 45 )
)
);
// JSL to create the column you want
// create a new column to preserve the order of the data
dt << new column("origRow", formula(row()));
dt:origRow << delete formula;
// Reverse the order of the data
dt << sort(by(:origRow), order(descending), replace table(1));
// create the new column
dt << new column( "col3", formula(
If( Row() == 1, x = :col1 );
If( Lag( :col2 ) != :col2,
x = :col1,
x = x * :col1
);
x;
));
// Since the formula is dependent on the order of the data, the formula needs
// to be removed and the values set to static values
dt:col3 << delete formula;
// reorder the data table back to the original order and delete the origRow column
dt << sort(by(:origRow), order(ascending), replace table(1));
dt << delete columns(:origRow);
Ed ecco un pezzo di JSL che creerà la nuova colonna senza ordinare
Names Default To Here( 1 );
// create the sample table
dt = New Table( "example",
Add Rows( 10 ),
New Column( "col1",
Numeric,
"Continuous",
Format( "Best", 12 ),
Set Values( [1, 2, 3, 2, 4, 5, 6, 7, 8, 9] ),
Set Display Width( 48 )
),
New Column( "col2",
Character( 1 ),
"Nominal",
Set Values( {"x", "x", "x", "y", "y", "y", "y", "z", "z", "z"} ),
Set Display Width( 45 )
)
);
// create the new column
dt << New Column( "col3b" );
:col3b[N Rows( dt )] = :col1[N Rows( dt )];
For( i = N Rows( dt ) - 1, i >= 1, i--,
If( :col2[i + 1] != :col2[i],
:col3b[i] = :col1[i],
:col3b[i] = :col3b[i + 1] * :col1[i]
)
);
Ciao Jim @txnelson
In realtà ha funzionato su una tabella più piccola (ovvero diverse migliaia di righe). Grazie.
Il "nuovo" problema che sto riscontrando è che la mia tabella di dati è molto grande. Quando ho incorporato la formula nella nuova colonna e ho fatto clic su "applica", il programma si è bloccato e ho dovuto uccidere jmp per uscire.
Mentre passo il mouse sopra la formula, ecco il messaggio di avviso relativo alla "tabella dati corrente".
"Current data table() ha effetti collaterali e di solito non è appropriato per essere utilizzato all'interno di una formula. Se questo è necessario, puoi usare expr o eval per impedire l'esecuzione nelle formule....."
Le mie capacità di scripting sono molto limitate. Grazie per il tuo ulteriore aiuto su questo argomento!
Saluti,
Tinghui
@txnelson ha scritto:
Ecco la nuova formula......è lo stesso metodo dell'ultima formula, ma basta trovare il punto di inizio e di fine per ciascuno dei gruppi.
If( Row() == 1,
curCol = :col2;
end = Max( Current Data Table() << get rows where( :col2 == curCol ) );
x = :col1;
,
:col2 != curCol;
curCol = :col2;
end = Max( Current Data Table() << get rows where( :col2 == curCol ) );
x = :col1;
);
For( i = Row() + 1, i <= end, i++,
x = x * :col1[i]
);
x;
Ecco la nuova formula......è lo stesso metodo dell'ultima formula, ma basta trovare il punto di inizio e di fine per ciascuno dei gruppi.
If( Row() == 1,
curCol = :col2;
end = Max( Current Data Table() << get rows where( :col2 == curCol ) );
x = :col1;
,
:col2 != curCol;
curCol = :col2;
end = Max( Current Data Table() << get rows where( :col2 == curCol ) );
x = :col1;
);
For( i = Row() + 1, i <= end, i++,
x = x * :col1[i]
);
x;

Ciao Jim @txnelson
Grazie per la tua risposta.
No, i nomi delle mie colonne non cambiano. Rimangono come col1, col2 come dato.Vorrei aggiungere una nuova colonna (col3) che esegue la moltiplicazione all'indietro per lo stesso valore dato in col2. Sto dimostrando il mio bisogno nella tabella seguente.Potresti per favore aiutare?
col1 col2 col3
1 x 6 (ovvero 1 x 2 x 3)
2 x 6 (ovvero 2 x 3)
3 x 3 (ovvero 3)
2 e 240 (ovvero 2x4x5x6)
4 y 120 (ovvero 4 x 5 x6)
5 y 30 (ovvero 5 x6)
6 e 6 (cioè 6)
7 z 504 (ovvero 7x8x9)
8 z 72 (ovvero 8x9)
9 z 9
Grazie!
Ho rimosso il mio post poiché mi mancava la variabile di raggruppamento. Il mio approccio non funzionerebbe in questo scenario.
Non capisco i tuoi 3 gruppi di colonne.Sembra che tu stia cambiando i nomi delle colonne nel mezzo di una tabella di dati, che non funzionerà in JMP.Questo formato di tabella proviene da un foglio di calcolo Excel?
Ecco una semplice formula che farà quello che vuoi per una tabella di dati che assomiglia

Allego la tabella dei dati.
La formula utilizzata è:
x = :col2[Row()];
If( Row() < N Rows( Current Data Table() ),
For( i = Row() + 1, i <= N Rows( Current Data Table() ), i++,
x = x * :col2[i]
)
);
x;
Questa stessa idea può essere utilizzata se ci sono più posti in una tabella di dati che devono riavviare la moltiplicazione.L'identificazione di quando ricominciare e quando finire dovrebbe solo essere elaborata