Concaténer plusieurs tables avec un ordre de colonnes différentÉquipe,
J'ai 5 fichiers CSV ayant chacun 200 colonnes (chaque fichier n'a pas le même nombre de colonnes). Chaque fichier comporte des colonnes dans un ordre différent. Je souhaite écrire un script qui permettra à l'utilisateur de sélectionner les 5 fichiers, puis de combiner les 5 fichiers (en supprimant les colonnes incompatibles) et d'enregistrer le fichier CSV combiné à l'emplacement requis. Je souhaite utiliser une commande similaire à (data = Open(Pick File("Choose the File", x)), x est le répertoire), pour sélectionner les fichiers.
Merci
Re : Concaténer plusieurs tables avec un ordre de colonnes différentMerci @txnelson
Vous êtes toujours d'une grande aide.Re : Concaténer plusieurs tables avec un ordre de colonnes différentVoici une refonte du script, en sélectionnant tous les fichiers à concaténer en une seule sélection, puis en exécutant un petit script pour les assembler, en ne gardant que les colonnes qui trouvent une correspondance. Je l'ai construit selon vos spécifications, mais il pourrait facilement être modifié pour permettre la concaténation de n'importe quel nombre de fichiers.
Names Default To Here( 1 );
inputDirectory = "C:\";
// Select the files to be read in......this can be any number of files
filePath = Pick File(
"Choose the File to be Concatenated to:",
inputDirectory,
{"CSV Files|csv;", "All Files|*"},
1,
0,
""
);
// Open the first file
dtMain = Open( filePath, invisible );
files = Pick File(
"Choose the Additional 4 Files to Read In:",
inputDirectory,
{"CSV Files|csv;", "All Files|*"},
1,
0,
"",
multiple
);
// Validate that files have been read in
If( Try( N Items( files ), 0 ) == 4,
Dialog( "Incorrect number of files were read in."
"Only 4 additional files can be read in");
Throw( "Incorrect number of files were read in" );
);
// Read in the remaining files and process them
For( i = 2, i <= N Items( Files ), i++,
Try( dtConCat = Open( Files[i], invisible ) );
mainColList = dtMain << Get Column Names( string );
conCatColList = dtConCat << Get Column Names( string );
// Delete the columns in the dtConCat table that do not exist in the dtMain table
delList = {};
For( k = 1, k <= N Items( conCatColList ), k++,
If( N Rows( Loc( mainColList, conCatColList[k] ) ) == 0,
Insert Into( delList, conCatColList[k] )
)
);
If( N Items( delList ) > 0,
dtConCat << delete columns( delList )
);
// Delete the columns in the dtMain table that were not found in the dtConCat table
delList = {};
For( k = 1, k <= N Items( mainColList ),
k++,
If( N Rows( Loc( conCatColList, mainColList[k] ) ) == 0,
Insert Into( delList, mainColList[k] )
)
);
If( N Items( delList ) > 0,
dtMain << delete columns( delList )
);
// If any columns still remain in the two tables, then concatenate them together
If( N Cols( dtMain ) > 0 & N Cols( dtConCat ) > 0,
dtMain = dtMain << Concatenate( dtConCat, Append to First Table )
);
// Close the no longer needed file
Close( dtConCat, nosave );
);
// Make the main file visible
dtMain << show window( 1 );
Re : Concaténer plusieurs tables avec un ordre de colonnes différent@Rajat ,
Je ne comprends pas pourquoi vous auriez besoin de créer une nouvelle table. Je ferais quelque chose comme ça.
dt = Open( "$SAMPLE_DATA/Big Class.jmp" );
OriginalColOrder = dt << Get Column Names("string");
dt << Reorder By Name();
SortedColOrder = dt << Get Column Names("string");
Show(OriginalColOrder);
Show(SortedColOrder); Les listes vous fournissent à la fois l'ordre de tri et l'ordre d'origine. Veuillez également partager ce que vous avez essayé jusqu'à présent, afin qu'il soit plus facile de voir où vous allez. Je ne parviens pas à comprendre exactement ce que vous avez essayé jusqu'à présent et où vous échouez. Si vous ne parvenez pas à partager vos données, essayez de créer des exemples de données afin que tout le monde puisse facilement recréer les problèmes et vous guider.
Re : Concaténer plusieurs tables avec un ordre de colonnes différent@uday_guntupalli
Puis-je m'aider à écrire la syntaxe pour enregistrer la commande d'origine et réorganiser la table finale avec la commande enregistrée ?
MerciRe : Concaténer plusieurs tables avec un ordre de colonnes différent@Rajat ,
dt << Reorder By Name();
Re : Concaténer plusieurs tables avec un ordre de colonnes différentMerci @uday_guntupalli
Si nous pouvons réorganiser les colonnes et leur donner le même ordre. Après cela, nous concaténerons toutes les tables.
Pouvez-vous m'aider à écrire la syntaxe pour réorganiser les colonnes de toutes les tables en fonction de la première table, puis nous utiliserons la commande concatenate dans une boucle. Si ce n'est pas possible, pouvons-nous enregistrer l'ordre d'origine des colonnes de la première table, puis réorganiser toutes les tables avec leur nom, puis les concaténer en boucle. Enfin, nous réorganiserons le tableau final en fonction de l'ordre des colonnes enregistré précédemment.
@Craige_Hales @txnelson avez-vous une solution à ce problème.
Merci. J'apprécie votre aide.Re : Concaténer plusieurs tables avec un ordre de colonnes différent@Rajat ,
ThisListAsAA = Associative Array(ThisList);
ThisListAsAAKeys =ThisListAsAA << Get Keys;
If(i == 1,
CommonItems = ThisListAsAAKeys;
,
// else
CommonItems << Intersect(ThisListAsAAKeys);
);
Un tableau associatif a une relation ou un mappage un à un. Ainsi, une fois que nous construisons un tableau associatif, la deuxième ligne tente d'extraire les clés uniques dans la carte du tableau associatif. Quant au bloc If, pensez à la théorie des ensembles, lorsque i = 1, nous attribuons les clés uniques du tableau associatif 1 au résultat. À partir de là, nous l'interconnectons à plusieurs reprises avec d'autres tableaux associatifs pour finalement arriver à une liste qui ne contiendra que des éléments communs à tous les tableaux associatifs.
Select( :name, :age, :sex, :height, :weight ),
By Row Number
C'était une faute de frappe dans mon exemple. Select(CommonItems) serait approprié.
Je ne sais pas si Concatenate fonctionnera, vous pouvez essayer
Re : Concaténer plusieurs tables avec un ordre de colonnes différent@uday_guntupalli
Merci pour votre grande aide.
j'ai quelques commentaires
- Tous les tableaux ont un nombre de lignes différent.
- Je veux concaténer (le nombre de lignes dans la table finale sera la somme du nombre de lignes de la table individuelle) les tables pour ne pas joindre les tables. La boucle de concaténation fonctionnera-t-elle de la même manière ?
Pourriez-vous également m'aider à comprendre les commandes suivantes.
- En boucle pour trouver les noms de colonnes communs. Pouvez-vous s'il vous plaît expliquer les lignes suivantes.
ThisListAsAA <SPAN class="token operator">=</SPAN> <SPAN class="token function">Associative Array</SPAN><SPAN class="token punctuation">(</SPAN>ThisList<SPAN class="token punctuation">)</SPAN><SPAN class="token punctuation">;</SPAN>
ThisListAsAAKeys <SPAN class="token operator">=</SPAN>ThisListAsAA <SPAN class="token operator"><</SPAN><SPAN class="token operator"><</SPAN><SPAN class="token messages"> Get Keys</SPAN><SPAN class="token punctuation">;</SPAN>
<SPAN class="token function">If</SPAN><SPAN class="token punctuation">(</SPAN>i <SPAN class="token operator">==</SPAN> <SPAN class="token number">1</SPAN><SPAN class="token punctuation">,</SPAN>
CommonItems <SPAN class="token operator">=</SPAN> ThisListAsAAKeys<SPAN class="token punctuation">;</SPAN>
<SPAN class="token punctuation">,</SPAN>
<SPAN class="token comment">// else </SPAN>
CommonItems <SPAN class="token operator"><</SPAN><SPAN class="token operator"><</SPAN><SPAN class="token messages"> Intersect</SPAN><SPAN class="token punctuation">(</SPAN>ThisListAsAAKeys<SPAN class="token punctuation">)</SPAN><SPAN class="token punctuation">;</SPAN>
<SPAN class="token punctuation">)</SPAN><SPAN class="token punctuation">;</SPAN>
Autant que j'ai compris dans " CetteListeEn tant qu'AA " , " Cette liste " sera stocké sous forme de tableau associatif. S'il vous plaît, aidez-nous à comprendre les deux lignes suivantes. - En boucle pour rejoindre les tables, pouvez-vous s'il vous plaît expliquer les lignes suivantes.
Select<SPAN class="token punctuation">(</SPAN> <SPAN class="token punctuation">:</SPAN>name<SPAN class="token punctuation">,</SPAN> <SPAN class="token punctuation">:</SPAN>age<SPAN class="token punctuation">,</SPAN> <SPAN class="token punctuation">:</SPAN>sex<SPAN class="token punctuation">,</SPAN> <SPAN class="token punctuation">:</SPAN>height<SPAN class="token punctuation">,</SPAN> <SPAN class="token punctuation">:</SPAN>weight <SPAN class="token punctuation">)</SPAN><SPAN class="token punctuation">,</SPAN>
By Row Number
Il n'y a pas de colonnes avec des noms de colonnes :name, :age etc et manuellement nous ne pouvons pas écrire pour sélectionner des colonnes car leur nombre est énorme. De plus, nous ne pouvons pas joindre par numéro de ligne car le nombre de lignes est différent et nous voulons concaténer la table sans la joindre.
Merci
Re : Concaténer plusieurs tables avec un ordre de colonnes différent@Rajat ,
Je fais l'hypothèse (je ne sais pas à quel point c'est valable) que vous avez le même nombre de lignes.
// Define Your Directory and a list to hold File Paths
MyDirectory = "C:\" ;
nFiles = 5;
MyFilePaths = {};
ColNamesListOfList = {};
OpenDts = {};
// Test if Directory exists and get all file paths
Try( If(Directory Exists(MyDirectory),
for(i = 1 , i <= nFiles, i ++,
FilePath = Pick File( "Select File", MyDirectory);
Insert Into(MyFilePaths,FilePath);
);
,
// else
Throw()
),
"Unable to Open File";
);
// Get List of All Column Names
for(i = 1, i <= nFiles, i++,
OpenDts[i] = Open(MyDirectory || "\" || FilePath[i],"Invisible");
ColNames = OpenDts[i] << Get Column Names("String");
Insert Into(ColNamesListOfList,ColNames);
);
// Find Common Column Names
for(i = 1, i <= nFiles, i++,
ThisList = ColNamesListOfList[i];
ThisListAsAA = Associative Array(ThisList);
ThisListAsAAKeys =ThisListAsAA << Get Keys;
If(i == 1,
CommonItems = ThisListAsAAKeys;
,
// else
CommonItems << Intersect(ThisListAsAAKeys);
);
);
// Concatenate
for(i = 1, i <= nFiles, i++,
If(i == 1,
dt_Results = OpenDts[i];
,
dt_Results << Join(With( OpenDts[i]),
Merge Same Name Columns,
Select( :name, :age, :sex, :height, :weight ),
By Row Number // assuming that the tables have the same number of rows
);
);
); Re : Concaténer plusieurs tables avec un ordre de colonnes différentMerci Uday. Je veux concaténer les colonnes communes.Re : Concaténer plusieurs tables avec un ordre de colonnes différent@Rajat ,
En regardant le problème que vous avez décrit, décomposons-le en plusieurs étapes.
Étape 1 : Sélection des fichiers souhaités - à l'aide de Pick File ()
),
"Unable to Open File";
); // Define Your Directory and a list to hold File Paths
MyDirectory = "C:\" ;
nFiles = 5;
MyFilePaths = {};
OpenDts = {};
// Test if Directory exists and get all file paths
Try( If(Directory Exists(MyDirectory),
for(i = 1 , i <= nFiles, i ++,
FilePath = Pick File( "Select File", MyDirectory);
Insert Into(MyFilePaths,FilePath);
); <BR /> , <BR /> // else<BR /> Throw()<BR />
Étape 2 : Parcourir les fichiers, ouvrir et concaténer les colonnes communes
Voilà, j'ai une question pour vous. Existe-t-il une liste de colonnes que vous attendez dans le tableau final (ou) s'agit-il uniquement des colonnes communes aux 5 fichiers CSV ?