Extraer palabras de una línea, como nombre de columna y sus números correspondientes como valores en la columnaTengo una columna llamada "Falla", donde tengo códigos de falla extraídos de varios dispositivos. A continuación se proporciona uno de los códigos de falla de un día en particular.
"inversor Inversor 20 por debajo del límite: 0,96 Kilovatios/inversor (58,9 % de 1,63 Kilovatios) al 30/11/2019 7:30:00 a. Kilovatios/inversor (57,9 % de 1,63 Kilovatios) a 30/11/2019 7:30:00 (dom az: 123,4 el: 3,7) Duración: 3,50 horas"
El objetivo es realizar un análisis para tabular los inversores defectuosos por fecha y su bajo rendimiento acumulado y duración; luego use los otros valores para diagnosticar la falla.
Necesito extraer los detalles de la siguiente manera en el formato ---- Nombre de columna: Valor
Inversor: 20
Por debajo del límite (kW/inversor): 0,96
% de máx.: 58,9 %
Fecha 30/11/2019
Hora : 7:30:00 AM
Domingo Az: 123.4
Elevación: 3.7
Duración (horas): 4
Si hay un segundo inversor que también tiene un código de falla, entonces (vea la segunda línea en el código de falla anterior)
Inversor: 23
Por debajo del límite (kW/inversor): 0,95
% de máx.: 57,9 %
Fecha 30/11/2019
Hora : 7:30:00 AM
Domingo Az: 123.4
Elevación: 3.7
Duración (horas) : 3.50
A veces puede haber 5 o 10 inversores (de 70) que pueden dar códigos similares en una sola línea.
¿Puede decirme cómo hacer esto? ¿Es solo a través de JSL? o puedo usar fórmulas? De cualquier manera, necesito ayuda.
Modelado Estadístico AvanzadoAutomatización y secuencias de comandosInvestigación del Consumidor y del MercadoLa personalización en masaIngeniería de Calidad y ProcesosRe: Extraer palabras de una línea, como nombre de columna y sus números correspondientes como valores en la columnaHola SunnyR,
Sé que esta es una publicación anterior, pero encontré el problema interesante y quería compartir una idea que a veces uso en situaciones similares a la tuya. Es muy poderoso (y simple) SI los datos están bien estructurados y no son demasiado complejos: el suyo califica.
NOTA: esta solución en particular asume que sus registros actualmente se encuentran en una sola columna de datos, que es la única columna de datos en la tabla. Como menciona, diferentes filas pueden contener diferentes números de registros de inversores.
Me di cuenta de que la palabra "horas" aparece solo al final del registro de cada inversor, por lo que podemos dividir los registros de registro de esta manera y apilar los datos. Una vez hecho esto, dividiremos el texto para mantener los números. Es importante que todos los registros tengan el mismo texto y medidas, siempre en el mismo orden, para que estos se alineen en columnas cuando rompamos el texto.
Convertiremos todas las columnas a numéricas, lo que hace que los datos no numéricos sean obvios, es decir, que falten. Eliminaremos los datos no numéricos, cambiaremos el nombre de las columnas y habremos terminado.
He adjuntado una tabla con un script de tabla para que pueda ver cómo funciona.
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" );Re: Extraer palabras de una línea, como nombre de columna y sus números correspondientes como valores en la columna¡Asombroso! Funciona. Gracias por su paciencia al escribir este código largo para cumplir con mi solicitud. Estoy tratando de implementar esto en otros códigos de Alerta que tengo. Muchas gracias. Me ahorró eones.
Re: Extraer palabras de una línea, como nombre de columna y sus números correspondientes como valores en la columnaTuve algo de tiempo libre... no hay mucho más que hacer con Covid-19, así que escribí un poco de JSL que debería darle un buen comienzo para leer sus datos.
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();
)
;
);
);Re: Extraer palabras de una línea, como nombre de columna y sus números correspondientes como valores en la columnaJim
Gracias por su sugerencia. Intentaré. Como soy nuevo en las secuencias de comandos, revisaré ejemplos para resolverlo.
Re: Extraer palabras de una línea, como nombre de columna y sus números correspondientes como valores en la columnaHe tenido que manejar datos como este muchas veces.El enfoque que creo que debe tomarse es leer todos los datos de su archivo de entrada en una tabla de datos JMP, donde cada línea completa se lee en una sola columna.Terminará con una tabla de datos con una columna y el número de filas igual al número de líneas en la tabla de datos de entrada.
A continuación, crea una nueva tabla con 3 columnas, Etiqueta, Valor y Línea.Luego, usando JSL que escanea el contenido de cada fila en una columna, uno crea una nueva fila en la nueva tabla y completa la Etiqueta (es decir, Inversor, Por debajo del límite (KW/Inversor), etc.), el Valor (es decir, 20 , 0.96, etc.) y la Línea, que sería simplemente el número de fila actual... Fila().Es posible que también deba haber una columna de salida adicional que se base en que este sea el primer inversor en la línea o el segundo inversor... etc.
Esto se puede hacer usando una función While() en combinación con la función Word() que busca ":" como delimitador.Las palabras impares serían las Etiquetas, las pares serían los Valores.
Una vez que se crea esta nueva tabla, puede moverse fácilmente a una fila por inversor, usando Tables=>Split.
Re: Extraer palabras de una línea, como nombre de columna y sus números correspondientes como valores en la columnadavid,
Sí, podría si solo tengo 1 o 2 inversores defectuosos, pero si, por ejemplo, tengo 23 códigos de falla en una sola línea para una sola fecha, entonces necesito crear tantas columnas individualmente y luego escribir fórmulas para cada uno de los 23 inversores. ¿Puede aclarar si estoy entendiendo su solución?También agregué otra línea que resume el objetivo del análisis después de la extracción.
Re: Extraer palabras de una línea, como nombre de columna y sus números correspondientes como valores en la columnaDebería poder progresar mucho en esto usando el editor de fórmulas: eche un vistazo a la función WORD