Analizza la stringa di una colonna e riempi un'altra colonnaCIAO,
Ho una tabella contenente ProductName e voglio generare la colonna OUTPUT.La colonna OUTPUT è una concatenazione di ProductID con Serial#. Come posso analizzare accuratamente il numero di serie e creare la colonna OUTPUT?
Esempi di numeri di serie:
- 07-08_13 significa Numero di serie 07, 08, 13
- 09-12 significa numero di serie 09, 10, 11, 12
- 01-03_05-08 significa numero di serie 01, 02, 03, 05, 06, 07, 08
- 01_04_05-08 significa numero di serie 01, 04, 05, 06, 07, 08
- 09_11_13_14 significa numero di serie 09,11,13,14

| Nome del prodotto | PRODUZIONE |
| AABBCC_07-08_13 | AABBCC-07 |
| AABBCC_07-08_13 | AABBCC-08 |
| AABBCC_07-08_13 | AABBCC-13 |
| AABBCC_09-12 | AABBCC-09 |
| AABBCC_09-12 | AABBCC-10 |
| AABBCC_09-12 | AABBCC-11 |
| AABBCC_09-12 | AABBCC-12 |
| EEFFGG_02 | EEFFGG-02 |
| HHIIJJ_01-07 | HHIIJJ-01 |
| HHIIJJ_01-07 | HHIIJJ-02 |
| HHIIJJ_01-07 | HHIIJJ-03 |
| HHIIJJ_01-07 | HHIIJJ-04 |
| HHIIJJ_01-07 | HHIIJJ-05 |
| HHIIJJ_01-07 | HHIIJJ-06 |
| HHIIJJ_01-07 | HHIIJJ-07 |
| KKLLLMM_01-03_05-08 | KKLLLMM-01 |
| KKLLLMM_01-03_05-08 | KKLLLMM-02 |
| KKLLLMM_01-03_05-08 | KKLLLMM-03 |
| KKLLLMM_01-03_05-08 | KKLLLMM-05 |
| KKLLLMM_01-03_05-08 | KKLLLMM-06 |
| KKLLLMM_01-03_05-08 | KKLLLMM-07 |
| KKLLLMM_01-03_05-08 | KKLLLMM-08 |
| NNOOPP_01_04_05-08 | NNOOPP-01 |
| NNOOPP_01_04_05-08 | NNOOPP-04 |
| NNOOPP_01_04_05-08 | NNOOPP-05 |
| NNOOPP_01_04_05-08 | NNOOPP-06 |
| NNOOPP_01_04_05-08 | NNOOPP-07 |
| NNOOPP_01_04_05-08 | NNOOPP-08 |
| QQRRSS_09_11_13_14 | QQRRSS_09 |
| QQRRSS_09_11_13_14 | QQRRSS_11 |
| QQRRSS_09_11_13_14 | QQRRSS_13 |
| QQRRSS_09_11_13_14 | QQRRSS_14 |
Modellazione statistica avanzataPersonalizzazione di massaRi: Analizza la stringa di una colonna e riempi un'altra colonnaSì, puoi, ma dovrai elaborare la logica su quando aggiungere nuove righe, ecc.Ciò che suggerisco è di eseguire il codice così com'è e quindi utilizzarlo
Tabelle=>Unisci
per mettere insieme le 2 tabelle di dati.
Ri: Analizza la stringa di una colonna e riempi un'altra colonnaCiao Jim,
È possibile farlo in modo che non ci sia dt2? Puoi aggiungere le colonne ProductID e Output in dt?
Grazie!
Ri: Analizza la stringa di una colonna e riempi un'altra colonnaPoiché i dati vengono immessi manualmente, molto probabilmente non gestirà tutti i casi speciali, ma sembra funzionare per i valori correnti:
Names Default To Here(1);
//Test table
/*
dt = New Table("Untitled 4993",
Compress File When Saved(1),
New Column("ProductName",
Character,
"Nominal",
Set Values(
{"AABBCC_07-08_13", "AABBCC_07-08_13", "AABBCC_07-08_13", "AABBCC_09-12", "AABBCC_09-12", "AABBCC_09-12", "AABBCC_09-12", "EEFFGG_02",
"HHIIJJ_01-07", "HHIIJJ_01-07", "HHIIJJ_01-07", "HHIIJJ_01-07", "HHIIJJ_01-07", "HHIIJJ_01-07", "HHIIJJ_01-07", "KKLLLMM_01-03_05-08",
"KKLLLMM_01-03_05-08", "KKLLLMM_01-03_05-08", "KKLLLMM_01-03_05-08", "KKLLLMM_01-03_05-08", "KKLLLMM_01-03_05-08", "KKLLLMM_01-03_05-08",
"NNOOPP_01_04_05-08", "NNOOPP_01_04_05-08", "NNOOPP_01_04_05-08", "NNOOPP_01_04_05-08", "NNOOPP_01_04_05-08", "NNOOPP_01_04_05-08",
"QQRRSS_09_11_13_14", "QQRRSS_09_11_13_14", "QQRRSS_09_11_13_14", "QQRRSS_09_11_13_14", "N4TA47_13-14-15-16-17-18", "N4TA59_13-19", "N4PX74-01-06"}
)
)
);
*/
dt = Current Data Table();
Summarize(dt, uniqProd = by(:ProductName));
newVals = Associative Array();
For Each({prodname_str}, uniqProd,
prodPart = Word(1, prodname_str, "_-");
serialPart = Substr(prodname_str, Length(prodPart) + 2);
//find and remove next range from serialPart
newVals[prodname_str] = {};
While(Length(serialPart) > 0 & serialPart != "_" & serialPart != "-",
nextRange = Regex(serialPart, "\d*-\d*");
If(IsMissing(nextRange),
break();
);
serialPart = Substitute(serialPart, nextRange, "");
If(Contains({"-", "_" }, Substr(serialPart, 1, 1)),
serialPart = Substr(serialPart, 2); //remove -_ if first character
);
nextRange = Words(nextRange, "-");
rangeVals = Index(Num(nextRange[1]), Num(nextRange[2]));
For Each({val}, rangeVals,
val = char(val);
val = Substr("00", Length(val) + 1) || val;
Insert Into(newVals[prodname_str], prodPart||"-"||val);
);
);
singleVals = Transform Each({val}, Words(serialPart, "_"),
val = char(val);
val = Substr("00", Length(val) + 1) || val;
prodPart||"-"||val;
);
Insert Into(newVals[prodname_str], singleVals);
);
vals = {{}, {}};
For Each({{key, value}}, newVals,
productname_list = Repeat({key}, N Items(value));
Insert Into(vals[1], productname_list);
Insert Into(vals[2], Sort List(value));
);
//add values to new table
dt = New Table("Productname",
New Column("ProductName", Character, "Nominal", Set Values({})),
New Column("OUTPUT", Character, "Nominal", Set Values({}))
);
dt:ProductName << Set Values(vals[1]);
dt:OUTPUT << Set Values(vals[2]);
Ri: Analizza la stringa di una colonna e riempi un'altra colonnaSi è verificato solo un piccolo errore in cui -1 non è stato rimosso quando ho ristrutturato il mio codice.

Names Default To Here( 1 );
dt = Current Data Table();
dt2 = New Table( "The Output",
New Column( "Product Name", character ),
New Column( "ProductID", Character ),
New Column( "OUTPUT", Character )
);
For( dtRow = 1, dtRow <= N Rows( dt ), dtRow++,
If( dtRow == 1 | dt:ProductName[dtRow - 1] != dt:ProductName[dtRow],
prodID = Word( 1, dt:ProductName[dtRow], "_" );
remainder = Substr( dt:ProductName[dtRow], Length( prodID ) + 2 );
While( Word( 1, remainder, "_" ) != "",
theWord = Word( 1, remainder, "_" );
If( Contains( theWord, "-" ),
numDigets = Length( Word( 1, theWord, "-" ) ) - 1;
zeros = Repeat( "0", numDigets );
For( loop = Num( Word( 1, theWord, "-" ) ),
loop <= Num( Word( 2, theWord, "-" ) ), loop++,
dt2 << Add rows( 1 );
theRow = N Rows( dt2 );
dt2:ProductName[theRow] = dt:ProductName[dtRow];
dt2:ProductID[theRow] = Word( 1, dt:ProductName[dtRow], "_-" );
dt2:output[theRow] = dt2:ProductID[theRow] || "-" ||
Substr( zeros, Length( Char( loop ) ) ) || Char( loop );
);
,
dt2 << Add Rows( 1 );
theRow = N Rows( dt2 );
dt2:output[theRow] = prodID || "-" || Word( 1, theWord, "-" );
dt2:ProductName[theRow] = dt:ProductName[dtRow];
dt2:ProductID[theRow] = Word( 1, dt:ProductName[dtRow], "_-" );
);
remainder = Substr( remainder, Length( theWord ) + 2 );
);
)
);
Assicurati di dedicare del tempo allo studio del codice, in modo da comprendere completamente come funziona.
Ri: Analizza la stringa di una colonna e riempi un'altra colonnaGrazie Jim ma l'OUTPUT sembra essere errato. Ad esempio le prime 3 righe, l'OUTPUT dovrebbe essere:
AABBCC-07
AABBCC-08
AABBCC-13
Ri: Analizza la stringa di una colonna e riempi un'altra colonnaI dati ProductName vengono inseriti manualmente. Queste sono eccezioni e miglioreranno nel tempo. Per favore ignorateli.
Ri: Analizza la stringa di una colonna e riempi un'altra colonnaEcco uno script che produce una nuova tabella che espande le righe come richiesto.Inserendo i dati in una nuova tabella, si aggira il problema relativo al numero di righe non sufficiente per l'espansione.Sembra gestire tutti i modelli conosciuti.

Names Default To Here( 1 );
dt = Current Data Table();
dt2 = New Table( "The Output",
New Column( "Product Name", character ),
New Column( "ProductID", Character ),
New Column( "OUTPUT", Character )
);
For( dtRow = 1, dtRow <= N Rows( dt ), dtRow++,
If( dtRow == 1 | dt:ProductName[dtRow - 1] != dt:ProductName[dtRow],
prodID = Word( 1, dt:ProductName[dtRow], "_" );
remainder = Substr( dt:ProductName[dtRow], Length( prodID ) + 2 );
While( Word( 1, remainder, "_" ) != "",
theWord = Word( 1, remainder, "_" );
If( Contains( theWord, "-" ),
numDigets = Length( Word( 1, theWord, "-" ) ) - 1;
zeros = Repeat( "0", numDigets );
For( loop = Num( Word( 1, theWord, "-" ) ) + 1,
loop <= Num( Word( 2, theWord, "-" ) ), loop++,
dt2 << Add rows( 1 );
theRow = N Rows( dt2 );
dt2:ProductName[theRow] = dt:ProductName[dtRow];
dt2:ProductID[theRow] = Word( 1, dt:ProductName[dtRow], "_-" );
dt2:output[theRow] = dt2:ProductID[theRow] || "-" ||
Substr( zeros, Length( Char( loop ) ) ) || Char( loop );
);
,
dt2 << Add Rows( 1 );
theRow = N Rows( dt2 );
dt2:output[theRow] = prodID || "-" || Word( 1, theWord, "-" );
dt2:ProductName[theRow] = dt:ProductName[dtRow];
dt2:ProductID[theRow] = Word( 1, dt:ProductName[dtRow], "_-" );
);
remainder = Substr( remainder, Length( theWord ) + 2 );
);
)
);Ri: Analizza la stringa di una colonna e riempi un'altra colonnaControllando rapidamente ci sono tre diversi problemi:
1. Infrangere la "regola" secondo cui c'è sempre la stessa quantità di nomi di prodotto che dovrebbero essere i seriali. N4TA59_13-19 nei dati solo una volta, dovrebbe essere 7 volte
2. Parte del numero di serie che non inizia con _ (N4PX74 - 01-06)
3. L'intervallo non inizia con _ (N4TA47_13-14-15-16-17-18) o questi dovrebbero essere solo valori singoli
Tutto ciò richiederà soluzioni diverse. Si tratta di problemi di qualità dei dati con i tuoi dati o lo script dovrebbe essere in grado di gestirli tutti?
Ri: Analizza la stringa di una colonna e riempi un'altra colonnaCiao Jthi,
Il tuo script non funzionerà se il mio ProductName è un misto di caratteri e numeri. Ho allegato una tabella. Ecco come apparirà la maggior parte del mio productName. Grazie per avermi aiutato.
Ri: Analizza la stringa di una colonna e riempi un'altra colonnaSe è così, dovrebbe già essere in grado di gestirlo. Ho apportato piccole modifiche (creazione della colonna OUTPUT se manca). Attualmente si basa sul fatto che il datatable è ordinato in base a ProductNames, il che potrebbe causare problemi a un certo punto, oppure puoi assicurarti che la tabella di input sia ordinata (soluzione più semplice).
Dovresti essere in grado di utilizzare la parte For Each che può essere utilizzata anche senza datatable purché tu abbia una variabile di elenco denominata uniqProd che abbia ProductNames. Dopodiché bisogna solo capire come aggiungere valori a datatable.
Names Default To Here(1);
//Test table
/*
dt = New Table("Untitled 4993",
Compress File When Saved(1),
New Column("ProductName",
Character,
"Nominal",
Set Values(
{"AABBCC_07-08_13", "AABBCC_07-08_13", "AABBCC_07-08_13", "AABBCC_09-12", "AABBCC_09-12", "AABBCC_09-12", "AABBCC_09-12", "EEFFGG_02",
"HHIIJJ_01-07", "HHIIJJ_01-07", "HHIIJJ_01-07", "HHIIJJ_01-07", "HHIIJJ_01-07", "HHIIJJ_01-07", "HHIIJJ_01-07", "KKLLLMM_01-03_05-08",
"KKLLLMM_01-03_05-08", "KKLLLMM_01-03_05-08", "KKLLLMM_01-03_05-08", "KKLLLMM_01-03_05-08", "KKLLLMM_01-03_05-08", "KKLLLMM_01-03_05-08",
"NNOOPP_01_04_05-08", "NNOOPP_01_04_05-08", "NNOOPP_01_04_05-08", "NNOOPP_01_04_05-08", "NNOOPP_01_04_05-08", "NNOOPP_01_04_05-08",
"QQRRSS_09_11_13_14", "QQRRSS_09_11_13_14", "QQRRSS_09_11_13_14", "QQRRSS_09_11_13_14"}
)
)
);
*/
dt = Current Data Table();
Summarize(dt, uniqProd = by(:ProductName));
valList = {};
For Each({prod}, uniqProd, //loop for each ProductName
prodPart = Word(1, prod, "_");
serialPart = Substr(prod, Contains(prod, "_") + 1); //remove start
possibleRanges = Words(serialPart, "_"); //if they contain -
For Each({val}, possibleRanges, //Loop for serialnumber inside the ProductName
If(Contains(val, "-"), //range
rangeVals = Words(val, "-");
For Each({val1}, Index(Num(rangeVals[1]), Num(rangeVals[2])),
valToAdd = Substr("0", Length(Char(val1))) || Char(val1);
Insert Into(valList, prodPart || "-" || valToAdd)
);
,
Insert Into(valList, prodPart || "-" || Substr("0", Length(Char(val))) || Char(val))
)
);
);
//if starting table doesn't have OUTPUT column create it
If(!Contains(dt << Get Column Names("String"), "OUTPUT"),
dt << New Column("OUTPUT", Character, "Nominal");
);
//dt[0,"OUTPUT"] = valList; subscripting, maybe a bit more difficult to understand
dt:OUTPUT << Set Values(valList);
Versione semplificata di ciò che lo script tenta di fare:
1. Lo script ottiene tutti i valori univoci nella colonna ProductName
2. Lo script esegue cicli su ciascuno di essi in due parti For Each loop
3. Il primo ciclo esegue il loop sui valori univoci e li divide in parti Prodotto e numero
4. La parte del numero di serie viene quindi ripetuta in loop per suddividerla in valori singoli. Questi singoli valori vengono concatenati con la parte Product e quindi la stringa viene inserita nell'elenco valList (questo 4. non è esattamente così semplice come ho spiegato qui).
5. Al termine di entrambi i cicli dovresti avere un elenco con tutti i possibili numeri di serie. La parte del prodotto sarà in ordine alfabetico.
6. Questo elenco viene quindi aggiunto a OUTPUT se esiste, in caso contrario viene prima creato.
Ri: Analizza la stringa di una colonna e riempi un'altra colonnaCiao Jthi,
Sì, il numero di righe corrispondeva al numero di numeri di serie.
Ri: Analizza la stringa di una colonna e riempi un'altra colonnaDovrebbe essere abbastanza facile. Nei dati estratti sono presenti tante righe quanti sono i numeri di serie?
Ri: Analizza la stringa di una colonna e riempi un'altra colonnaCiao Jthi,
Grazie per lo script, ma la mia tabella è in realtà dinamica. Ogni giorno estrarrò questa tabella da un database con un intervallo di date diverso e verranno visualizzati diversi set di ProductName. Quindi non sono sempre 32 righe. Il tuo script può quasi funzionare ma puoi gestire la dimensione dell'array? Grazie.
Ri: Analizza la stringa di una colonna e riempi un'altra colonnaCiao chris,
Ho uno script che affronterà alcuni ProductName e talvolta analizzerà in modo errato. Puoi rivedere e aggiungere codici per indirizzare quei ProductNames che non funzionano finora?
Funzionerà per gli esempi seguenti:
EEFFGG_02
HHIIJJ_01-07
KKLLLMM_01-03_05-08
Non funzionerà ancora per gli esempi seguenti:
AABBCC_07-08_13
NNOOPP_01_04_05-08
QQRRSS_09_11_13_14
dt=current data table();
(dt << New Column( "ProductID", Character )) << Set Selected;
(dt << New Column( "OUTPUT", Character )) << Set Selected;
//Parse string in ProductName column
For Each Row(
dt,
//Assign the ProductID value
:ProductID = Word( 1, :ProductName, "_-" ); //"_"
//If the ProductName changes, capture the start and end
If( :ProductName != Lag( :ProductName, 1 ),
start = Num( Word( 2, :ProductName, "_-" ) );
end = Num( Word( 3, :ProductName, "_-" ) );
);
//Assign the OUTPUT value
:OUTPUT = :ProductID || "-" || Repeat( "0", 2 - Length( Char( start ) ) ) || Char( start );
//After end value & there is an _, set start to value after _
If( start == end & Contains( :ProductName, "_"),
start = Num( Word(-2, :ProductName, "_-" ) ),
start++);
);
Ri: Analizza la stringa di una colonna e riempi un'altra colonnaOk, questo potrebbe funzionare. Richiede JMP16 a causa dell'utilizzo di For Each (può essere sostituito con For per altre versioni. Questa è una soluzione fortemente basata su script, con pochi o nessun commento e richiederà una tabella iniziale specifica per funzionare (è necessaria la colonna OUTPUT).
Names Default To Here(1);
dt = New Table("Untitled 4993",
Add Rows(32),
Compress File When Saved(1),
New Column("ProductName",
Character,
"Nominal",
Set Values(
{"AABBCC_07-08_13", "AABBCC_07-08_13", "AABBCC_07-08_13", "AABBCC_09-12", "AABBCC_09-12", "AABBCC_09-12", "AABBCC_09-12", "EEFFGG_02",
"HHIIJJ_01-07", "HHIIJJ_01-07", "HHIIJJ_01-07", "HHIIJJ_01-07", "HHIIJJ_01-07", "HHIIJJ_01-07", "HHIIJJ_01-07", "KKLLLMM_01-03_05-08",
"KKLLLMM_01-03_05-08", "KKLLLMM_01-03_05-08", "KKLLLMM_01-03_05-08", "KKLLLMM_01-03_05-08", "KKLLLMM_01-03_05-08", "KKLLLMM_01-03_05-08",
"NNOOPP_01_04_05-08", "NNOOPP_01_04_05-08", "NNOOPP_01_04_05-08", "NNOOPP_01_04_05-08", "NNOOPP_01_04_05-08", "NNOOPP_01_04_05-08",
"QQRRSS_09_11_13_14", "QQRRSS_09_11_13_14", "QQRRSS_09_11_13_14", "QQRRSS_09_11_13_14"}
)
),
New Column("OUTPUT",
Character(16),
"Nominal",
Set Values({"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", ""})
)
);
Summarize(dt, uniqProd = by(:ProductName));
valList = {};
For Each({prod}, uniqProd,
prodPart = Word(1, prod, "_");
serialPart = Substr(prod, Contains(prod, "_") + 1); //remove start
possibleRanges = Words(serialPart, "_"); //if they contain -
For Each({val}, possibleRanges,
If(Contains(val, "-"), //range
rangeVals = Words(val, "-");
For Each({val1}, Index(Num(rangeVals[1]), Num(rangeVals[2])),
valToAdd = Substr("0", Length(Char(val1))) || Char(val1);
Insert Into(valList, prodPart || "-" || valToAdd)
);
,
Insert Into(valList, prodPart || "-" || Substr("0", Length(Char(val))) || Char(val))
)
);
);
dt[0,"OUTPUT"] = valList;Mi chiedo se qualcosa del genere possa essere fatto "facilmente" con la corrispondenza dei modelli di JMP @Craige_Hales
Ri: Analizza la stringa di una colonna e riempi un'altra colonnaGrazie ma preferisco un jsl piuttosto che il delimitatore interattivo. Il tuo metodo non ha risolto lo scenario in cui il numero di serie 09-12. Dovrebbe produrre righe come di seguito. Non solo AABBCC-09 e AABBCC-12. Il "-" significa "a" che significa intervallo. Quindi 09-12 significa 09, 10, 11, 12.
| AABBCC_09-12 | AABBCC-09 |
| AABBCC_09-12 | AABBCC-10 |
| AABBCC_09-12 | AABBCC-11 |
| AABBCC_09-12 | AABBCC-12 |
Ri: Analizza la stringa di una colonna e riempi un'altra colonnaOh, hai ragione. il - viene interpretato come un intervallo e il _ viene interpretato come un vero delimitatore di elementi
Ri: Analizza la stringa di una colonna e riempi un'altra colonna@jthi ,
Mi hai battuto sul tempo.
La tua spiegazione è più dettagliata e anche quello a cui stavo pensando.
Ri: Analizza la stringa di una colonna e riempi un'altra colonnaCIAO @cchueng ,
Ci sono un paio di modi. Alcuni sono basati su script (cerca una risposta da qualcuno che lo suggerisce con un esempio) oppure potresti utilizzare cicli successivi di Testo in colonne (esempio trovato qui Risolto: come posso dividere il testo di una colonna in più colonne? - Comunità di utenti JMP) Quindi potresti concatenare le colonne desiderate selezionandole e quindi utilizzare una formula di colonna o utilizzare l'opzione Nuova colonna formula dopo aver fatto clic con il pulsante destro del mouse su una delle colonne selezionate. Cerca le opzioni Carattere per concat.La formula di colonna è più flessibile e offre molte opzioni. Consulta la guida su questo argomento ( Crea formule in JMP )
Spero che questo ti dia qualche indicazione.
Migliore,
Ri: Analizza la stringa di una colonna e riempi un'altra colonnaMolto probabilmente potresti scrivere una formula con Lag per farlo (o uno script con JSL), ma puoi anche provare a farlo in modo interattivo ma ci vogliono alcuni passaggi:
1. Seleziona la colonna NomeProdotto
2. Vai alle colonne Cols/Utilities/Text To e usa sia - che _ come delimitatori

3. Vai su Tabelle e Stack e aggiungi tutto il resto oltre alla prima colonna alla selezione Stack Columns


5. Rimuovere la colonna Etichetta
6. Seleziona entrambe le colonne a sinistra e vai su Righe/Selezione riga/Seleziona righe duplicate ed elimina quelle righe

7. Seleziona una cella con un valore vuoto e scegli Seleziona celle corrispondenti ed elimina quelle righe
8. Ora scegli entrambe le colonne e fai clic con il pulsante destro del mouse sull'intestazione della colonna e crea la formula

9. Apri la formula appena creata e modifica , in _

10. Rinominare ed eliminare colonne/formule
11. Se ne hai bisogno ProductName lì, dovresti essere in grado di mantenerlo lì se non lo elimini accidentalmente nel primo passaggio come ho fatto io

Se devi avere - o _ a seconda del numero di serie, molto probabilmente potresti gestirlo nella formula concatenata
Modifica: ho controllato la domanda in modo un po 'più accurato e questo è un po' più complicato di quanto ho mostrato qui. Dovrai aggiungere calcoli per alcuni numeri di serie perché sono tra numeri. Questa soluzione non funzionerà in questi perché alcune righe verranno rimosse quando vengono rimossi i duplicati.