从行中提取单词作为列名,并将其相应的数字作为值提取到列中我有一个名为“故障”的列,其中有从各种设备中提取的故障代码。 下面给出了某一天的故障代码之一。
“逆变器 逆变器 20 低于限制:0.96 千瓦/逆变器(1.63 千瓦的 58.9 %),2019 年 11 月 30 日上午 7:30:00(太阳 az:123.4 el:3.7) 持续时间:4.00 小时 逆变器 23 低于限制:0.95千瓦/逆变器(1.63 千瓦的 57.9 %),2019 年 11 月 30 日上午 7:30:00(太阳 az:123.4 el:3.7)持续时间:3.50 小时"
目标是执行分析,按日期及其累积性能和持续时间列出故障逆变器;稍后使用其他值来诊断故障。
我需要按以下格式提取详细信息:----列名:值
逆变器:20个
低于限制(kW/逆变器):0.96
最大百分比:58.9%
日期 11/30/2019
时间 : 上午 7:30:00
太阳 AZ : 123.4
海拔:3.7
持续时间(小时):4
如果有第二个逆变器也有故障代码(请参阅上面故障代码中的第二行)
逆变器:23
低于限制(kW/逆变器):0.95
最大百分比:57.9%
日期 11/30/2019
时间 : 上午 7:30:00
太阳 AZ : 123.4
海拔:3.7
持续时间(小时):3.50
有时可能有 5 或 10 个逆变器(总共 70 个),它们可以在一行中给出类似的代码。
你能让我知道如何完成这件事吗? 只能通过JSL吗?或者我可以使用公式吗? 不管怎样——我需要一些帮助。
高级统计建模自动化和脚本编写消费者和市场研究大规模定制质量和工艺工程回复:从行中提取单词作为列名称,并将其相应的数字作为值提取到列中嗨桑尼R,
我知道这是一篇旧帖子,但我发现这个问题很有趣,并且想分享我有时在与您类似的情况下使用的想法。 如果数据结构良好且不太复杂(您的数据符合条件),那么它就非常强大(而且简单)。
注意:此特定解决方案假设您的日志当前位于单数据列中,这是表中唯一的数据列。 正如您所提到的,不同的行可能包含不同数量的逆变器日志。
我注意到“小时”一词仅出现在每个逆变器日志的末尾,因此我们可以通过这种方式打破日志记录并堆叠数据。 完成后,我们将分解文本以保留数字。 重要的是,所有日志都具有相同的文本和测量值,并且始终以相同的顺序 - 因此当我们分解文本时,这些将在列中对齐。
我们将所有列转换为数字,这使得非数字数据变得明显,即缺失。 我们将删除非数字数据,重命名列,然后就完成了。
我附上了一个带有表格脚本的表格,以便您可以了解其工作原理。
Names Default To Here( 1 );
dt = :log << get data table; // for use within a table script. otherwise, use dt = current data table();
// can break up the logs at "hours". Replace with ~ or some other unused character to delimit.
For( i = 1, i <= N Row( dt ), i++,
dt:log[i] = Substitute( dt:log[i], "hours", "~" )
);
//split the logs using this delimiter
dt << Text to Columns( delimiters( "~" ), columns( :log ) );
// some logs had more inverters than others, so the stack my have empty data in some rows. Delete them.
dt2 = dt << stack( columns( (dt << get column names)[2 :: N Col( dt )] ) );
dt2 << delete rows(dt2 << get rows where (:data == ""));
//using parens and spaces as delimiters, break up each log
dt2 << text to columns( delimiters( " ()" ), columns( :data ) );
//deal with date and time. They're always in the same columns, making this easier
dt2 << New Column( "date", formula( Informat( :data 14 ) ) );
dt2 << New Column( "time", formula( Informat( :data 15 || " " || :data 16 ) ) );
dt2:date << Delete Formula;
dt2:time << Delete Formula;
dt2 << delete columns( {"data 14", "data 15"} ); //else these persist later, as they are numeric
//Remove non-numeric columns by changing all columns to numeric and removing those containing only missing data.
//Proceed "backward" as deletions change indices.
For( i = N Col( dt2 ), i >= 1, i--,
Column( dt2, i ) << set data type( numeric );
If( N Row( Loc( dt2:i << get values ) ) == 0, dt2 << delete columns( i ) );
);
//rename columns and reformat date and time.
colNames = Words( "Inverter,Below Limit(kw/inverter),% of max,Max,Sun Az,Elevation,Duration", "," );
For( i = 1, i <= N Items( colNames ), i++, Column( dt2, i ) << set name( colNames[i] ) );
dt2:date << Format( "m/d/y" );
dt2:time << Format( "h:m:s" );回复:从行中提取单词作为列名称,并将其相应的数字作为值提取到列中惊人的! 它有效。感谢您耐心编写这段长代码来完成我的请求。 我正在尝试将其实现到我拥有的其他警报代码中。非常感谢。它为我节省了很多时间。
回复:从行中提取单词作为列名称,并将其相应的数字作为值提取到列中我有一些空闲时间......没有太多其他事情可做,因为 Covid-19 仍然存在,所以我写了一些 JSL,这应该可以为您读取数据提供一个良好的开端
Names Default To Here( 1 );
dt = Open(
"Path to the data file",
columns( New Column( "c000001", Character, "Nominal" ) ),
Import Settings(
End Of Line( CRLF, CR, LF ),
End Of Field( CSV( 0 ) ),
Strip Quotes( 1 ),
Use Apostrophe as Quotation Mark( 0 ),
Use Regional Settings( 0 ),
Scan Whole File( 1 ),
Treat empty columns as numeric( 0 ),
CompressNumericColumns( 0 ),
CompressCharacterColumns( 0 ),
CompressAllowListCheck( 0 ),
Labels( 0 ),
Column Names Start( 1 ),
Data Starts( 1 ),
Lines To Read( "All" ),
Year Rule( "20xx" )
)
);
// Create the new output data table
dtLong = New Table( "Long Data",
New Column( "Label", character ),
New Column( "Value", character ),
New Column( "Line" ),
New Column( "Instance" )
);
// A function that returns the next word in the line and
// then removes the word from the front of the target line
getWord = Function( {},
theWord = Trim( Word( 1, target, " " ) );
target = Trim( Substr( target, Length( theWord ) + 1 ) );
theWord;
);
// Loop through all rows in the input data table
For( i = 1, i <= N Rows( dt ), i++,
instance = 0;
target = Column( dt, 1 )[i];
While( Word( 1, target, " " ) != "",
dtLong << add rows( 1 );
dtLong:line[N Rows( dtLong )] = i;
theWord = getWord();
Match( theWord,
"inverter",
instance++;
dtLong:Instance[N Rows( dtLong )] = instance;
dtLong:Label[N Rows( dtLong )] = theWord;
theWord = getWord();
theWord = getword();
dtLong:value[N Rows( dtLong )] = theWord;,
"below",
dtLong:Instance[N Rows( dtLong )] = instance;
dtLong:Label[N Rows( dtLong )] = theWord || " limit (KW/Inverter)";
theWord = getWord();
theWord = getWord();
dtLong:value[N Rows( dtLong )] = theWord;
// Get the % of Max
dtLong << Add Rows( 1 );
dtLong:line[N Rows( dtLong )] = i;
dtLong:Instance[N Rows( dtLong )] = instance;
theWord = getWord();
theWord = getWord();
dtLong:Label[N Rows( dtLong )] = "% of Max";
dtLong:value[N Rows( dtLong )] = Substr( theWord, 2 );
// Skip forward to the Date
For( k = 1, k <= 5, k++,
theWord = getWord()
);
// Get the Date
dtLong << add rows( 1 );
theWord = getWord();
dtLong:Instance[N Rows( dtLong )] = instance;
dtLong:line[N Rows( dtLong )] = i;
dtLong:Label[N Rows( dtLong )] = "Date";
dtLong:value[N Rows( dtLong )] = theWord;
// Get the Time
dtLong << add rows( 1 );
theWord = getWord();
dtLong:Instance[N Rows( dtLong )] = instance;
dtLong:line[N Rows( dtLong )] = i;
dtLong:Label[N Rows( dtLong )] = "Time";
dtLong:value[N Rows( dtLong )] = theWord || getWord();
// Get the Sun Az
dtLong << add rows( 1 );
theWord = getWord();
dtLong:Instance[N Rows( dtLong )] = instance;
dtLong:line[N Rows( dtLong )] = i;
dtLong:Label[N Rows( dtLong )] = Substr( theWord, 2 ) || " " || getWord();
dtLong:value[N Rows( dtLong )] = getWord();
// Get the Elevation
dtLong << add rows( 1 );
theWord = getWord();
dtLong:Instance[N Rows( dtLong )] = instance;
dtLong:line[N Rows( dtLong )] = i;
dtLong:Label[N Rows( dtLong )] = "Elevation";
dtLong:value[N Rows( dtLong )] = Word( -1, getWord(), ")" );,
"Duration:",
dtLong:Instance[N Rows( dtLong )] = instance;
dtLong:Label[N Rows( dtLong )] = theWord || " (hrs)";
dtLong:value[N Rows( dtLong )] = getWord();
theWord = getWord();
)
;
);
);回复:从行中提取单词作为列名称,并将其相应的数字作为值提取到列中吉姆
谢谢你的建议。 我会尝试。 由于我是脚本编写新手,我将通过示例来弄清楚。
回复:从行中提取单词作为列名称,并将其相应的数字作为值提取到列中我曾多次不得不处理这样的数据。我认为必须采取的方法是将输入文件中的所有数据读入 JMP 数据表,其中每个完整行都读入单个列。您最终将得到一个包含一列的数据表,行数等于输入数据表中的行数。
接下来,您创建一个包含 3 列的新表:标签、值和行。然后,使用 JSL 扫描一列中每一行的内容,在新表中创建一个新行,并填充标签(即逆变器、低于限制(KW/逆变器)等)、值(即 20) 、0.96 等)和 Line,它只是当前行号.....Row()。可能还必须有一个额外的输出列,该输出列将基于这是线路上的第一个逆变器或第二个逆变器......等等。
这可以使用 While() 函数结合 Word() 函数扫描“:”作为分隔符来完成。奇数编号的单词将是标签,偶数编号的单词将是值。
创建此新表后,您可以使用“表”=>“拆分”轻松移至每个逆变器一行。
回复:从行中提取单词作为列名称,并将其相应的数字作为值提取到列中戴夫,
是的,如果我只有 1 或 2 个有故障的逆变器,我可以,但是,例如,如果我在单个日期的一行中有 23 个故障代码,那么我需要单独创建这么多列,然后为每个故障编写公式23个逆变器。 您能否澄清一下我是否理解您的解决方案。我还添加了另一行,总结了提取后分析的目标。
回复:从行中提取单词作为列名称,并将其相应的数字作为值提取到列中使用公式编辑器您应该能够在这方面取得很大进展 - 看看 WORD 函数