J'utilise le script ci-dessous pour calculer la moyenne et l'écart type robustes. Il fonctionne correctement jusqu'à 1 million de lignes, mais sur une table contenant environ 5 millions de lignes, le calcul a pris 45 secondes. Existe-t-il une méthode plus efficace pour obtenir ces résultats ?
Names Default To Here( 1 );
// 0. Guard: ensure at least one data table is open
If( N Table() == 0,
Throw( "No data table is open. Please open a data table first." )
);
dt = Current Data Table();
// 1. Ask user to select a numeric column
dlg = Column Dialog(
yCol = Col List( "Select a Numeric Column", Min Col( 1 ), Max Col( 1 ), Data Type( "Numeric" ) )
);
If( dlg["Button"] == -1, Throw( "User cancelled" ) );
selectedCol = dlg["yCol"][1];
colName = selectedCol << Get Name;
t1 = Tick Seconds();
// 2. Run Distribution with Robust Mean and Robust Std Dev enabled
dist = dt << Distribution(
Continuous Distribution(
Column( selectedCol ),
Outlier Box Plot Row Cutoff( 100000000 ),
Customize Summary Statistics(
Robust Mean( 1 ),
Robust Std Dev( 1 )
)
),
Invisible
);
Wait(0);
// 3. Extract Robust Mean and Robust Std Dev from the Summary Statistics table
distRep = dist << Report;
robustMean = .;
robustSigma = .;
Try(
// Navigate to the Summary Statistics outline box for the selected column
summBox = distRep[Outline Box( colName )][Outline Box( "Summary Statistics" )];
// Get the Name column (col 1) and Value column (col 2) from the table
nameCol = summBox[String Col Box( 1 )] << Get;
valueCol = summBox[Number Col Box( 1 )] << Get;
// Search for Robust Mean and Robust Std Dev rows by name
For( i = 1, i <= N Items( nameCol ), i++,
If( Contains( nameCol[i], "Robust Mean" ),
robustMean = valueCol[i]
);
If( Contains( nameCol[i], "Robust Standard Deviation" ),
robustSigma = valueCol[i]
);
);
,
Print( "Warning: Could not navigate report structure. Check outline box names." );
);
// 4. Display results
New Window( "Robust Statistics Results",
V List Box(
Text Box( "Column: " || colName ),
Text Box( "Robust Mean: " || (If( Is Missing( robustMean ),
"Not available", Char( robustMean, 10, 4 ) )) ),
Text Box( "Robust Std Dev: " || (If( Is Missing( robustSigma ),
"Not available", Char( robustSigma, 10, 4 ) )) )
)
);
// ------------------------
t2 = Tick Seconds();
Print( "Total Ticks: " || Char( Round( t2 - t1, 3 ) ) || " seconds" );
Je ne vois pas d'autre méthode, au sein de jmp uniquement, pour calculer les deux statistiques robustes dont vous avez besoin. Cependant, vous pourriez envisager d'utiliser l'interface Python pour voir si elle serait plus rapide sur les grandes tables. Voici un exemple :
Names Default To Here(1);
// --- PARAMETERS ---
dt = Open("$SAMPLE_DATA/Semiconductor Capability.jmp" );
colName = "npn1"; // <-- change to your column name
col = Column(dt, colName) << Get Values;
// Send column data to Python
Python Send( col );
c = 1.345; // Huber tuning constant
tol = 1e-6;
maxIter = 50;
// Run Python code
Python Submit(
"
import numpy as np
x = np.array(col, dtype=float)
x = x[~np.isnan(x)] # remove missing values
# --- Initialization ---
mu = np.median(x)
mad = np.median(np.abs(x - mu))
sigma = 1.4826 * mad if mad > 0 else np.std(x)
c = " || Char(c) || "
tol = " || Char(tol) || "
maxIter = " || Char(maxIter) || "
for _ in range(maxIter):
u = (x - mu) / sigma
# Huber weights
w = np.ones_like(u)
mask = np.abs(u) > c
w[mask] = c / np.abs(u[mask])
# Update mean
mu_new = np.sum(w * x) / np.sum(w)
# Update sigma
u = (x - mu_new) / sigma
sigma_new = sigma * np.sqrt(np.mean(np.minimum(u**2, c**2)))
# Check convergence
if abs(mu_new - mu) < tol and abs(sigma_new - sigma) < tol:
break
mu, sigma = mu_new, sigma_new
huber_mean = mu
huber_std = sigma
print( huber_mean, huber_std )
"
);
// Retrieve results from Python
huber_mean = Python Get(huber_mean);
huber_std = Python Get( huber_std);
show( huber_mean, huber_std);
Quel est l'objectif du calcul de ces statistiques ? La méthode utilisée par JMP avec la plateforme Distribution (estimateur M, nécessitant de nombreux calculs) est-elle celle que vous souhaitez utiliser, ou une autre méthode plus rapide (médiane et écart interquartile, par exemple) conviendrait-elle ? Pourriez-vous également envisager un échantillonnage préalable de vos données ?