列の文字列を解析して別の列を埋めるこんにちは、
ProductName を含むテーブルがあり、OUTPUT 列を生成したいと考えています。OUTPUT 列は、ProductID と Serial# を連結したものです。 Serial# を正確に解析して OUTPUT 列を作成するにはどうすればよいですか?
シリアル番号の例:
- 07-08_13 はシリアル番号 07、08、13 を意味します
- 09-12 はシリアル番号 09、10、11、12 を意味します
- 01-03_05-08 はシリアル番号 01、02、03、05、06、07、08 を意味します
- 01_04_05-08 はシリアル番号 01、04、05、06、07、08 を意味します
- 09_11_13_14 はシリアル番号 09,11,13,14 を意味します

| 商品名 | 出力 |
| 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 | KKLLMM-01 |
| KKLLLMM_01-03_05-08 | KKLLMM-02 |
| KKLLLMM_01-03_05-08 | KKLLMM-03 |
| KKLLLMM_01-03_05-08 | KKLLMM-05 |
| KKLLLMM_01-03_05-08 | KKLLMM-06 |
| KKLLLMM_01-03_05-08 | KKLLMM-07 |
| KKLLLMM_01-03_05-08 | KKLLMM-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 |
高度な統計モデリングマスカスタマイゼーションRe: 列の文字列を解析して別の列を埋めるはい、可能ですが、新しい行をいつ追加するかなどについてロジックを検討する必要があります。私がお勧めするのは、コードをそのまま実行してから使用することです。
テーブル=>結合
2 つのデータ テーブルを結合します。
Re: 列の文字列を解析して別の列を埋めるこんにちは、ジムさん
dt2がないようにすることはできますか? dt に ProductID 列と Output 列を追加できますか?
ありがとう!
Re: 列の文字列を解析して別の列を埋めるデータは手動で入力されるため、すべての特殊なケースを処理できるわけではありませんが、現在の値では機能しているようです。
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]);
Re: 列の文字列を解析して別の列を埋めるコードを再構築したときに -1 が削除されなかったという小さなエラーがありました。

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 );
);
)
);
コードがどのように機能するかを完全に理解するために、必ず時間をかけてコードを研究してください。
Re: 列の文字列を解析して別の列を埋めるJim に感謝しますが、出力が間違っているようです。 たとえば、最初の 3 行の出力は次のようになります。
AABBCC-07
AABBCC-08
AABBCC-13
Re: 列の文字列を解析して別の列を埋めるProductName データは手動で入力されます。 これらは例外であり、時間の経過とともに改善されます。 無視してください。
Re: 列の文字列を解析して別の列を埋めるこれは、要求に応じて行を展開する新しいテーブルを生成するスクリプトです。データを新しいテーブルに配置することで、展開に十分な行数がないという問題が回避されます。既知のパターンをすべて処理できるようです。

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 );
);
)
);Re: 列の文字列を解析して別の列を埋める3 つの異なる問題があることを簡単に確認します。
1. シリアルと同じ量の ProductName が常に存在するという「ルール」を破ります。 データ内の N4TA59_13-19 は 1 回のみ、7 回必要です
2. シリアル番号部分が_で始まっていない(N4PX74 - 01-06)
3. 範囲が _ (N4TA47_13-14-15-16-17-18) で始まらないか、これらは単一の値である必要があります
これらすべてに異なる修正が必要になります。 これらのデータ品質の問題はデータにありますか、それともスクリプトでこれらすべてを処理できる必要がありますか?
Re: 列の文字列を解析して別の列を埋めるこんにちは。
ProductName に文字と数字が混在している場合、スクリプトは機能しません。 テーブルを付けました。 私の productName の大部分はこのようになります。 助けてくれてありがとう。
Re: 列の文字列を解析して別の列を埋めるその場合は、すでに対応できるはずです。 小さな変更を加えました(OUTPUT列が存在しない場合は作成)。 現時点では、データテーブルが ProductNames でソートされているという事実に依存しているため、ある時点で問題が発生する可能性があります。そうでない場合は、入力テーブルがソートされていることを確認することができます (最も簡単な解決策)。
ProductNames を持つ uniqProd という名前のリスト変数がある限り、For Each 部分はデータテーブルなしでも使用できるはずです。 後は、データテーブルに値を追加する方法を理解するだけです。
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);
スクリプトが実行しようとする内容の簡略版:
1. スクリプトは ProductName 列の一意の値をすべて取得します
2. スクリプトは 2 つの部分からなる For Each ループでそれぞれをループします。
3. 最初のループは一意の値をループし、それらを Product 部分と数値部分に分割します。
4. 次に、シリアル番号部分を再度ループして、単一の値に分割します。 これらの単一の値は Product 部分と連結され、文字列が valList リストに挿入されます (この 4. は、ここで説明したほど単純ではありません)。
5. 両方のループが終了すると、考えられるすべてのシリアル番号を含むリストが作成されます。 製品部分はアルファベット順になります。
6. このリストは、存在する場合は OUTPUT に追加され、存在しない場合は最初に作成されます。
Re: 列の文字列を解析して別の列を埋めるこんにちは。
はい、行数はシリアル番号の数と一致しました。
Re: 列の文字列を解析して別の列を埋めるそれはかなり簡単なはずです。 取得したデータには、シリアル番号と同じ数の行が含まれていますか?
Re: 列の文字列を解析して別の列を埋めるこんにちは。
スクリプトをありがとう。しかし、私のテーブルは実際には動的です。 毎日、異なる日付範囲でデータベースからこのテーブルを取得すると、異なる ProductName セットが表示されます。 したがって、常に 32 行になるわけではありません。 スクリプトはほぼ機能しますが、配列サイズに対処できますか? ありがとう。
Re: 列の文字列を解析して別の列を埋めるこんにちは、クリスさん
ProductName の一部に対処するスクリプトがありますが、時々間違って解析されます。 これまでのところ機能していない ProductName に対処するコードを確認して追加していただけますか?
以下の例では機能します。
EEFFGG_02
HHIIJJ_01-07
KKLLLMM_01-03_05-08
以下の例ではまだ機能しません:
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++);
);
Re: 列の文字列を解析して別の列を埋めるわかりました、これはうまくいくかもしれません。 For Each を使用するため、JMP16 が必要です (他のバージョンの場合は For に置き換えることができます)。 これは高度にスクリプト化されたソリューションであり、コメントはほとんどまたはまったくなく、動作するには特定の開始テーブルが必要です (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;JMP 独自のパターン マッチングを使用して、このようなことが「簡単に」実行できないか疑問に思っています@Craige_Hales
Re: 列の文字列を解析して別の列を埋めるありがとう、でも私はインタラクティブな区切り文字よりも jsl の方が好きです。 あなたの方法では、シリアル番号が異なる場合のシナリオに対処していませんでした。 09-12。 以下のような行が出力されるはずです。 AABBCC-09 と AABBCC-12 だけではありません。 「-」は範囲を意味する「to」を意味します。 つまり、09-12 は 09、10、11、12 を意味します。
| AABBCC_09-12 | AABBCC-09 |
| AABBCC_09-12 | AABBCC-10 |
| AABBCC_09-12 | AABBCC-11 |
| AABBCC_09-12 | AABBCC-12 |
Re: 列の文字列を解析して別の列を埋めるああ、その通りです。 - は範囲として解釈され、_ は項目の実際の区切り文字として解釈されます。
Re: 列の文字列を解析して別の列を埋める@jthi 、
あなたは私をそれに打ち負かしました。
あなたの説明はより詳細であり、私も考えていたことです。
Re: 列の文字列を解析して別の列を埋めるこんにちは@cchueng 、
いくつかの方法があります。 スクリプトベースのものもあります (サンプルを使ってこれを提案している人からの返信を探してください) または、Text to Columns の連続ラウンドを使用することもできます (サンプルはここにあります)解決済み: 列内のテキストを複数の列に分割するにはどうすればよいですか? - JMP ユーザーコミュニティ)次に、目的の列を選択して連結し、列の式を使用するか、選択した列の 1 つを右クリックして [新しい式の列] オプションを使用します。 concat の文字オプションを探します。列の式はより柔軟で、多くのオプションが提供されます。このトピックのヘルプを参照してください ( JMP で式を作成する)
それが何らかの方向性を与えてくれることを願っています。
最高、
Re: 列の文字列を解析して別の列を埋めるおそらく、これを行うには Lag を使用して式を書く (または JSL を使用してスクリプトを書く) ことができますが、対話的に実行することもできますが、かなりの手順が必要です。
1. ProductName列を選択します
2. Cols/Utilities/Text To 列に移動し、- と _ の両方を区切り文字として使用します。

3. [テーブルとスタック] に移動し、最初の列以外のすべてを [スタック列] 選択に追加します。


5. ラベル列を削除する
6. 残っている両方の列を選択し、「行」/「行の選択」/「重複する行の選択」に移動し、それらの行を削除します。

7. 値が空のセルを 1 つ選択し、[一致するセルの選択] を選択してそれらの行を削除します。
8. 両方の列を選択し、列ヘッダーを右クリックして式を作成します。

9. 作成した数式を開き、「,」を「_」に変更します。

10. 列/数式の名前変更と削除
11. 必要な場合は、 ProductName がそこにあります。私のように最初のステップで誤って削除しなければ、そこに保持できるはずです

シリアル番号に応じて - または _ が必要な場合は、おそらく連結式で処理できます。
編集:質問をもう少し正確に確認しましたが、これはここで示したものよりも少し複雑です。 シリアル番号の一部は番号の間にあるため、計算を追加する必要があります。 重複が削除されると一部の行も削除されるため、この解決策はこれらの場合には機能しません。