Extraire des mots d'une ligne - en tant que nom de colonne et ses numéros correspondants en tant que valeurs dans la colonneJ'ai une colonne nommée "Fault" - où j'ai des codes d'erreur extraits de divers appareils. L'un des codes d'erreur d'un jour particulier est donné ci-dessous.
"onduleur Onduleur 20 sous la limite : 0,96 kilowatts/onduleur (58,9 % de 1,63 kilowatts) au 30/11/2019 7:30:00 AM (sun az : 123,4 el : 3,7) Durée : 4,00 heures onduleur Onduleur 23 sous la limite : 0,95 Kilowatts/onduleur (57,9 % de 1,63 Kilowatts) au 30/11/2019 7:30:00 AM (sun az: 123.4 el: 3.7) Durée : 3.50 heures"
L'objectif est d'effectuer une analyse pour classer les onduleurs défectueux par date et leurs sous-performances et durées cumulées ; utiliser ultérieurement les autres valeurs pour diagnostiquer le défaut.
J'ai besoin d'extraire les détails comme suit dans le format ----Column name : Value
Inverseur : 20
Sous limite (kW/Inverter) : 0.96
% du maximum : 58,9 %
Date 30/11/2019
Heure : 7:30:00
Soleil Az : 123.4
Altitude : 3,7
Durée (h) : 4
S'il y a un deuxième onduleur qui a également un code d'erreur alors (voir la deuxième ligne dans le code d'erreur ci-dessus)
Onduleur : 23
Sous limite (kW/Inverter) : 0.95
% du maximum : 57,9 %
Date 30/11/2019
Heure : 7:30:00
Soleil Az : 123.4
Altitude : 3,7
Durée (h) : 3.50
Parfois, il peut y avoir 5 ou 10 onduleurs (sur 70) qui peuvent donner des codes similaires sur une seule ligne.
Pouvez-vous me dire comment y parvenir. Est-ce uniquement via JSL ? ou puis-je utiliser des formules? Quoi qu'il en soit, j'ai besoin d'aide.
Modélisation statistique avancéeAutomatisation et scriptÉtudes de consommation et de marchéPersonnalisation de masseIngénierie de la qualité et des procédésRe : Extraire des mots d'une ligne - en tant que nom de colonne et ses numéros correspondants en tant que valeurs dans la colonneBonjour SunnyR,
Je sais que c'est un vieux post, mais j'ai trouvé le problème intéressant et je voulais partager une idée que j'utilise parfois dans des situations similaires à la vôtre. C'est très puissant (et simple) SI les données sont bien structurées et pas trop complexes - les vôtres sont éligibles.
REMARQUE : cette solution particulière suppose que vos journaux se trouvent actuellement dans une seule colonne de données, qui est la seule colonne de données du tableau. Comme vous l'avez mentionné, différentes lignes peuvent contenir différents nombres de journaux d'onduleurs.
J'ai remarqué que le mot "heures" n'apparaît qu'à la fin du journal de chaque onduleur, nous pouvons donc casser les enregistrements du journal de cette façon et empiler les données. Une fois cela fait, nous décomposerons le texte pour conserver les chiffres. Il est important que tous les journaux aient le même texte et les mêmes mesures, toujours dans le même ordre, afin qu'ils soient alignés en colonnes lorsque nous cassons le texte.
Nous allons convertir toutes les colonnes en numériques, ce qui rend les données non numériques évidentes, c'est-à-dire manquantes. Nous allons supprimer les données non numériques, renommer les colonnes et nous aurons terminé.
J'ai joint un tableau avec un script de tableau afin que vous puissiez voir comment cela fonctionne.
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 : Extraire des mots d'une ligne - en tant que nom de colonne et ses numéros correspondants en tant que valeurs dans la colonneIncroyable! Cela fonctionne. Merci pour votre patience dans l'écriture de ce long code pour accomplir ma demande. J'essaie d'implémenter cela sur d'autres codes d'alerte que j'ai. Merci beaucoup. Cela m'a fait économiser des éons.
Re : Extraire des mots d'une ligne - en tant que nom de colonne et ses numéros correspondants en tant que valeurs dans la colonneJ'avais un peu de temps libre ...... pas grand-chose d'autre à faire avec Covid-19 encore là, alors j'ai écrit un peu de JSL qui devrait vous donner un bon départ pour lire vos données
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 : Extraire des mots d'une ligne - en tant que nom de colonne et ses numéros correspondants en tant que valeurs dans la colonneJim
Merci pour votre suggestion. J'essaierai. Comme je suis nouveau dans les scripts, je vais passer par des exemples pour le comprendre.
Re : Extraire des mots d'une ligne - en tant que nom de colonne et ses numéros correspondants en tant que valeurs dans la colonneJ'ai dû gérer des données comme celle-ci plusieurs fois.L'approche qui, à mon avis, doit être adoptée consiste à lire toutes les données de votre fichier d'entrée dans une table de données JMP, où chaque ligne complète est lue dans une seule colonne.Vous vous retrouverez avec une table de données avec une colonne et le nombre de lignes égal au nombre de lignes dans la table de données d'entrée.
Ensuite, vous créez un nouveau tableau avec 3 colonnes, Label, Value et Line.Ensuite, en utilisant JSL qui scanne le contenu de chaque ligne dans une colonne, on crée une nouvelle ligne dans la nouvelle table, et remplit l'étiquette (c'est-à-dire l'onduleur, en dessous de la limite (KW/onduleur) etc.), la valeur (c'est-à-dire 20 , 0,96, etc.) et la Ligne, qui serait simplement le numéro de ligne actuel .....Row().Il peut également y avoir une colonne de sortie supplémentaire qui serait basée sur le fait qu'il s'agit du 1er onduleur sur la ligne, ou du 2ème onduleur ..... etc.
Cela peut être fait en utilisant une fonction While() en combinaison avec la fonction Word() en recherchant ":" comme délimiteur.Les mots impairs seraient les étiquettes, les mots pairs seraient les valeurs.
Une fois cette nouvelle table créée, vous pouvez facilement vous déplacer dans une ligne par onduleur, en utilisant Tables=>Split.
Re : Extraire des mots d'une ligne - en tant que nom de colonne et ses numéros correspondants en tant que valeurs dans la colonneDavid,
Oui, je pourrais si j'ai juste 1 ou 2 onduleurs défectueux, mais si par exemple j'ai 23 codes d'erreur sur une seule ligne pour une seule date, je dois créer autant de colonnes individuellement, puis écrire des formules pour chacun des 23 onduleurs. Pouvez-vous préciser si je comprends votre solution.J'ai aussi ajouté une autre ligne qui résume le but de l'analyse après extraction.
Re : Extraire des mots d'une ligne - en tant que nom de colonne et ses numéros correspondants en tant que valeurs dans la colonneVous devriez pouvoir faire beaucoup de progrès à ce sujet en utilisant l'éditeur de formules - jetez un œil à la fonction WORD