解析一列的字符串并填充另一列你好,
我有一个包含 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 | 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 | NNOPP-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 | NNOPP-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 |
高级统计建模大规模定制回复:解析一列的字符串并填充另一列是的,你可以,但是你必须弄清楚何时添加新行等的逻辑。我的建议是,您所做的就是按原样运行代码,然后使用
表=>连接
将 2 个数据表放在一起。
回复:解析一列的字符串并填充另一列嗨吉姆,
可以做到没有dt2吗? 您可以在 dt 中添加 ProductID 和 Output 列吗?
谢谢!
回复:解析一列的字符串并填充另一列由于数据是手动输入的,因此很可能无法处理所有特殊情况,但似乎适用于当前值:
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]);
回复:解析一列的字符串并填充另一列它只是有一个小错误,当我重组代码时,-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 );
);
)
);
请确保您花时间研究代码,以便完全理解它是如何工作的。
回复:解析一列的字符串并填充另一列谢谢吉姆,但输出似乎不正确。 例如前 3 行,输出应该是:
AABBCC-07
AABBCC-08
AABBCC-13
回复:解析一列的字符串并填充另一列ProductName 数据是手动输入的。 这些都是例外情况,并且会随着时间的推移而改善。 请忽略他们。
回复:解析一列的字符串并填充另一列这是一个生成新表的脚本,该表根据请求扩展行。通过将数据放入新表中,它绕过了行数不足用于扩展的问题。它似乎确实可以处理所有已知的模式。

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 );
);
)
);回复:解析一列的字符串并填充另一列快速检查存在三个不同的问题:
1. 打破了 ProductNames 数量始终与序列号数量相同的“规则”。 N4TA59_13-19中的数据只有一次,应该是7次
2. 序列号部分不以 _ 开头 (N4PX74 - 01-06)
3. 范围不以 _ 开头 (N4TA47_13-14-15-16-17-18) 或者这些应该只是单个值
所有这些都需要不同的修复。 这些数据质量问题是否与您的数据有关,或者脚本是否应该能够处理所有这些问题?
回复:解析一列的字符串并填充另一列嗨,jthi,
如果我的 ProductName 是字符和数字的混合,您的脚本将无法工作。 我附上了一张桌子。 这就是我的大部分产品名称的样子。 谢谢你的协助。
回复:解析一列的字符串并填充另一列如果是这样的话,应该已经可以应付了。 我做了一些小的修改(如果缺少输出列,则创建它)。 目前,它确实依赖于数据表按 ProductNames 排序的事实,这可能会在某些时候导致问题,或者您可以确保输入表已排序(最简单的解决方案)。
您应该能够使用 For Each 部分,甚至可以在没有数据表的情况下使用,只要您有名为 uniqProd 且具有 ProductNames 的列表变量。 之后只是弄清楚如何向数据表添加值。
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. 脚本循环遍历两部分 For Each 循环中的每一个
3. 第一个循环遍历唯一值并将它们拆分为 Product 和 number 部分
4. 然后再次循环序列号部分,将其拆分为单个值。 这些单个值与 Product 部分连接,然后将字符串插入到 valList 列表中(这 4. 并不完全像我在这里解释的那么简单)。
5. 两个循环完成后,您应该得到一个列表,其中包含所有可能的序列号。 产品部分将按字母顺序排列。
6. 如果该列表存在,则将该列表添加到 OUTPUT,如果不存在,则首先创建该列表。
回复:解析一列的字符串并填充另一列嗨,jthi,
是的,行数与序列号数匹配。
回复:解析一列的字符串并填充另一列这应该相当容易。 提取的数据中的行数是否与序列号一样多?
回复:解析一列的字符串并填充另一列嗨,jthi,
感谢您的脚本,但我的表实际上是动态的。 每天,我都会从具有不同日期范围的数据库中提取此表,并且会出现不同的 ProductName 集。 所以并不总是 32 行。 你的脚本几乎可以工作,但是你能解决数组大小吗? 谢谢。
回复:解析一列的字符串并填充另一列嗨克里斯,
我有一个脚本可以处理一些 ProductName,有时会错误地解析。 您能否检查并添加代码来解决那些迄今为止不起作用的 ProductNames?
适用于以下示例:
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++);
);
回复:解析一列的字符串并填充另一列好的,这可能有用。 由于使用了 For Each(对于其他版本可以用 For 替换),因此需要 JMP16。 这是一个大量脚本化的解决方案,几乎没有注释,并且需要特定的起始表才能工作(需要 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
回复:解析一列的字符串并填充另一列谢谢,但我更喜欢 jsl 而不是交互式分隔符。 您的方法没有解决序列号时的情况09-12。 它应该输出如下所示的行。 不仅仅是 AABBCC-09 和 AABBCC-12。 “-”表示“至”,表示范围。 所以 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 |
回复:解析一列的字符串并填充另一列哦,你的权利。 - 被解释为范围,_ 被解释为项目的真正分隔符
回复:解析一列的字符串并填充另一列@jthi ,
你比我先一步。
你的解释比较详细,也是我的想法。
回复:解析一列的字符串并填充另一列你好@cchueng ,
有几种方法。 有些是脚本基础(寻找有人建议的回复和示例),或者您可以使用连续几轮的文本到列(示例在此处找到)已解决:如何将一列中的文本拆分为多列? - JMP 用户社区)然后,您可以通过选择所需的列来连接它们,然后使用列公式或右键单击所选列之一后使用“新建公式列”选项。 查找连接的字符选项。列公式更加灵活,为您提供了很多选项,请参阅有关此主题的帮助(在 JMP 中创建公式)
我希望这能给你一些指导。
最好的,
回复:解析一列的字符串并填充另一列您很可能可以使用 Lag 编写一个公式来执行此操作(或使用 JSL 编写脚本),但您也可以尝试以交互方式执行此操作,但这需要相当多的步骤:
1. 选择“产品名称”列
2. 转到 Cols/Utilities/Text To 列并使用 - 和 _ 作为分隔符

3. 转到“表和堆栈”,并将除第一列之外的所有其他内容添加到“堆栈列”选择中


5. 删除标签列
6. 选择剩下的两列,然后转到行/行选择/选择重复行并删除这些行

7. 选择一个具有空值的单元格,然后选择“选择匹配单元格”并删除这些行
8. 现在选择两个列并右键单击列标题并创建公式

9.打开刚刚创建的公式,将,更改为_

10.重命名和删除列/公式
11. 如果您需要ProductName 在那里,如果你不像我一样在第一步中不小心删除了它,你应该能够将它保留在那里

如果您必须有 - 或 _ 取决于序列号,您很可能可以在连接公式中处理它
编辑:我更准确地检查了这个问题,这比我在这里展示的要复杂一些。 您必须为某些序列号添加计算,因为它们位于数字之间。 此解决方案不适用于这些情况,因为删除重复项时某些行将被删除。