Formula per sottrarre la media di un sottoinsieme da una colonna di dati?Sto cercando un modo per prendere un sottoinsieme di una tabella di dati che utilizza solo righe che corrispondono a una condizione specificata e sottrarre la media di tali righe da una colonna.
Ad esempio, utilizzando il set di dati Big Class, supponiamo che voglia creare una nuova colonna da mostrare "Differenza di altezza tra questo studente e il quattordicenne medio dello stesso sesso."
Il modo in cui so come farlo è aggiungendo una seconda tabella, utilizzando Tabelle -> Riepilogo -> Statistiche: Media (altezza), Gruppo: sesso, Sottogruppo: età. Quindi posso Tabella -> Aggiorna: Big Class By (sex), Match columns: sex = sex, e questo aggiungerà diverse colonne per Mean(height, [age]). Quindi posso creare una nuova colonna "Delta altezza vs 14 anni dello stesso sesso" che è :altezza - :Mean(altezza, 14).
La mia domanda: esiste un modo per evitare di creare una tabella aggiuntiva e la colonna aggiuntiva (ad esempio "Mean(height, 14)")? Sembra che Col Mean(x, byVar) sia vicino a fornire questa funzionalità, ma non ha la funzionalità per selezionare un gruppo diverso; ad esempio potrei usare :height - Col Mean(:height, :age, :sex) per trovare il delta tra lo studente X e lo studente medio del suo stesso sesso e altezza, ma non so se c'è un modo per specificare in Col Significa che voglio considerare solo le righe con età=14, anziché utilizzare il valore età associato a quella riga.
Faccio questo tipo di normalizzazione molto frequentemente, quindi qualsiasi cosa per renderla più semplice e veloce sarebbe enormemente apprezzata!
Combinazione e pulizia dei datiRi: Formula per sottrarre la media di un sottoinsieme da una colonna di dati?Bellissimo! Grazie!!!
Ri: Formula per sottrarre la media di un sottoinsieme da una colonna di dati?CIAO @MarkJSchwab ,
Sì, capisco come racchiudere tutto questo nei condizionali potrebbe non essere l'ideale in molti casi. Ecco una modifica a @brady_brady la soluzione che dovrebbe funzionare (tabella allegata):

testVal = :sex;
:height - Mean( :height[(:height << get datatable) << get rows where( :age == 14 & :sex == testVal )] );
In questo caso, prendiamo il valore di :sex per la riga corrente e lo salviamo in una variabile, testVal. Quindi, quando valutiamo la funzione di centratura, possiamo testare l'utilizzo di quel valore nella funzione get rows where().
Ecco la tabella con una colonna composta solo dalle righe selezionate da questa funzione Get Rows Where():

Come puoi vedere, tutte le righe utilizzano 14 anni come sottoinsieme, ma quale sottoinsieme di sesso è determinato dai valori correnti della riga del sesso. Dovrebbe essere facilmente adattabile a diversi livelli di complessità.
@giuliano
Ri: Formula per sottrarre la media di un sottoinsieme da una colonna di dati?Hai solo bisogno di espandere la formula per gestire sia i maschi che le femmine
If( :sex == "F",
:height - Mean( :height[(:height << get datatable) << get rows where( :age == 14 & :sex == "F" )] ),
:height - Mean( :height[(:height << get datatable) << get rows where( :age == 14 & :sex == "M" )] )
)
Ri: Formula per sottrarre la media di un sottoinsieme da una colonna di dati?CIAO @giuliano Grazie ancora per l'aiuto!
Un'ultima precisazione: idealmente vorrei sottrarre l'età media delle ragazze di 14 anni dalle ragazze, e l'età media dei ragazzi di 14 anni sottratta dai ragazzi. (Nel tuo esempio, stai sottraendo l'età di 14 anni sia dai ragazzi che dalle ragazze.)
(Mi rendo conto che in questo caso specifico con solo M/F sarebbe facile usare un condizionale e dire "Se :sex == 'F' allora usa questa formula, se :sex == 'M' allora modifica la formula in dire {mean(:height[(:height << get datatable) << get rows where( :age == 14 & :sex == "M" )])}" ma nei miei casi d'uso più generali potrei avere un un gran numero di gruppi e condizionali nidificati diventerebbero ingombranti.)
Qualche modo semplice per raggiungere questo obiettivo?
Ri: Formula per sottrarre la media di un sottoinsieme da una colonna di dati?CIAO @MarkJSchwab ,
Sembra che <
Ecco una soluzione dalla procedura guidata jmp @brady_brady :
:height - Mean( :height[(:height << get datatable) << get rows where( :age == 14 )] )

Vale la pena dedicare un momento a scompattare questa formula perché ci sono alcuni metodi che scommetto che troverai utili da utilizzare in seguito.
(:height << get datatable) << get rows where( :age == 14 )
restituirà la matrice delle voci di riga in cui :age==14. È importante sottolineare che puoi modificare la funzione get rows where() per abbinare qualsiasi ricerca desideri, inclusa la seconda richiesta che credo tu abbia di includere un'altra variabile. Per esempio:
(:height << get datatable) << get rows where( :age == 14 & :sex == "F"

Ora che abbiamo una matrice di righe che corrisponde alla tua condizione, Brady usa questa matrice per pedice :height.
height[(:height << get datatable) << get rows where( :age == 14 & :sex == "F" )]

Ciò restituirà la matrice dei valori di :height per ciascuna di quelle righe, in questo caso, le altezze delle studentesse di 14 anni: [61, 62, 65, 63, 62]
Infine, la funzione Mean() è racchiusa attorno a questa matrice, che restituisce la media necessaria per calcolare la variabile centrata:
mean(:height[(:height << get datatable) << get rows where( :age == 14 & :sex == "F" )])

Questa soluzione è più flessibile, tollerante nei confronti dei dati mancanti e funziona con le versioni precedenti di jmp, quindi penso che nel complesso sia una soluzione migliore. Grazie, @brady_brady !
@giuliano
Ri: Formula per sottrarre la media di un sottoinsieme da una colonna di dati?CIAO @giuliano , grazie per il suggerimento. Sfortunatamente quando incollo quella formula esatta
Col Mean( :height, <<FREQ></FREQ>
nella mia Big Class, restituisce 62,55 (ovvero la media complessiva della colonna senza selezionare età=14) invece del valore corretto che vedi di 64,166.
Posso anche scaricare il tuo allegato e i valori corretti vengono visualizzati nella colonna "Centrato rispetto alla media all'età == 14". Ma se creo una nuova colonna in quella tabella con la stessa identica formula, restituisce valori diversi (mostrando [altezza] - [altezza media complessiva], invece di mostrare correttamente [altezza] - [altezza media di 14 anni]).
Sto utilizzando JMP Pro 14.3.0. Qualche idea su come posso far sì che il mio output corrisponda al tuo?
E un'altra domanda, sul tuo foglio, se aggiungi un byVar aggiuntivo di :sex (per la formula totale ":height - (Col Mean( :height, :sex, <Ri: Formula per sottrarre la media di un sottoinsieme da una colonna di dati?
CIAO @MarkJSchwab ,
C'è un modo semplice per farlo usando Col Mean() che non è ovvio finché non lo vedi. Col Mean() accetta un argomento della colonna Frequenza:

Di solito, questo è necessario quando è necessario pesare utilizzando un'altra colonna. Ma, nel tuo esempio, cosa succederebbe se potessimo ponderare i valori di Age==14 come 1 e tutti gli altri valori come 0? Questo ci darebbe una media solo di quegli individui in cui Età==14. Possiamo farlo direttamente nella formula:
Col Mean( :height, <<FREQ></FREQ>

Questo restituirà:

Ora, per la tua domanda specifica, centrando rispetto a questa specifica media dall'altezza, possiamo inserirla nella formula nel solito modo:
:height - (Col Mean( :height, <<FREQ></FREQ>


Spero che aiuti!
@giuliano
Ri: Formula per sottrarre la media di un sottoinsieme da una colonna di dati?Ciao, MarkJSchwab!
Naturalmente c'è un modo per fare ciò che desideri.JSL ti renderà libero!
Ho scritto un semplice script che utilizza principalmente la capacità di JSL di scrivere uno script per te.Provalo:
// Title: Bigclass Normalization Script for JMP User Community discussion
// Purpose: Demonstrate how to write a very basic script to do "normalizations"
Names Default To Here( 1 );
Bigclass_dt = Open( "$SAMPLE_DATA\Big Class.jmp" );
BigclassSummary_dt = bigclass_dt << Summary( Group( :age, :sex ), Mean( :height ) );
BigclassSummary_dt << Select Where( :Age != 14 ) << Delete Rows;
Bigclass_dt << Join(
With( BigclassSummary_dt ),
Select( :name, :age, :sex, :height ),
SelectWith( :Name( "Mean(height)" ) ),
By Matching Columns( :sex = :sex ),
Drop multiples( 0, 0 ),
Include Nonmatches( 0, 0 ),
Preserve main table order( 1 ),
Output Table( "NormedBigclass by AgeGender" )
);
BigclassJoin_dt = Data Table( "NormedBigclass by AgeGender" ) << New Column( "Normalized",
numeric,
continuous,
Formula( :Name( "height" ) - :Name( "Mean(height)" ) ),
evalFormula
);
Close( BigclassSummary_dt, NoSave );
Ho creato una tabella riepilogativa separata e poi l'ho chiusa, ma non devi farlo in questo modo.
Esistono, ovviamente, modi più sofisticati per scrivere uno script come questo, soprattutto perché tutte le clausole "where" sono codificate e potresti riscontrare problemi con questo script se la tua tabella dati è grande, ma, anche se JSL sarà la tua strada verso la produttività.Esistono molte ottime risorse per imparare JSL!
Buona fortuna!