Aide script concaténation intelligente sur deux fichiers

Aide script concaténation intelligente sur deux fichiers - Python - Programmation

Marsh Posté le 12-08-2009 à 14:32:08    

Bonjour à tous,
 
je fais appel à vous car je n'arrive pas a avoir un script correct qui me permette la concaténation de deux fichiers sur deux champs en 1 temps correct.
 
J'ai 2 fichiers, l'un de 440 000 lignes et l'autre de 10 000 lignes.
 
Les lignes ne se correspondent pas d'un fichier à l'autre. Une des lignes peut se retrouver en face de n'importe quelle autre du second fichier du moment ou le code_art et la campagne correspondent.  
 
Il y aura plusieurs correspondance car si les code_art sont uniques, il y a plusieurs campagnes.  
 
je sais que c'est un peu compliqué alors je vais vous redonner un exemple.  
 
Premier fichier ex :

Code :
  1. mag code_art campagne st_juill st_aout st_sept st_oct st_nov­ st_dec st_janv st_fevr st_mars st_avril st_mai st_juin
  2. 206 176 2007 6.00 4.00 5.00 5.00 3.00 5.00 8.00 7.00 6.00 10­.00 10.00 10.00
  3. 206 176 2008 10.00 6.00 5.00 3.00 9.00 9.00 6.00 7.00 7.00 5­.00 8.00 7.00
  4. 206 176 2009 5.00 5.00
  5. 206 183 2007 6.00 6.00 4.00 7.00 6.00 6.00 8.00 4.00 8.00 6.­00 5.00 6.00
  6. 206 183 2008 6.00 6.00 6.00 6.00 5.00 5.00 1.00 6.00 6.00 6.­00 7.00
  7. 206 183 2009 8.00 8.00

         
 
ou le premier champs correspond à un code magasin (il y en a environ 80), le deuxième champs correspond au code article et le troisième champs qui indique la campagne.  
 
Le deuxième fichier ex :

Code :
  1. code_art campagne pmaar_juill pmaar_aout pmaar_sept pmaar_oc­t pmaar_nov pmaar_dec pmaar_janv pmaar_fevr pmaar_mars pmaar­_avril pmaar_mai pmaar_juin pmasr_juill pmasr_aout pmasr_sep­t pmasr_oct pmasr_nov pmasr_dec pmasr_janv pmasr_fevr pmasr_­mars pmasr_avril pmasr_mai pmasr_juin
  2. 176 2007 2.146 2.146 2.146 2.195 2.195 2.229 2.229 2.229 2.2­29 2.229 2.229 2.228 2.146 2.146 2.146 2.195 2.195 2.229 2.2­29 2.229 2.229 2.229 2.229 2.228
  3. 176 2008 2.267 2.267 2.267 2.267 2.267 2.267 2.276 2.276 2.2­76 2.276 2.276 2.276 2.267 2.267 2.267 2.267 2.267 2.267 2.2­76 2.276 2.276 2.276 2.276 2.276
  4. 176 2009 2.229            2.229
  5. 183 2007 3.538 3.658 3.658 3.704 3.704 3.574 3.574 3.574 3.5­74 3.574 3.574 3.574 3.538 3.658 3.658 3.704 3.704 3.574 3.5­74 3.574 3.574 3.574 3.574 3.574
  6. 183 2008 3.574 3.574 3.574 3.574 3.574 3.574 3.606 3.606 3.6­06 3.606 3.606 3.606 3.574 3.574 3.574 3.574 3.574 3.574 3.6­06 3.606 3.606 3.606 3.606 3.606
  7. 183 2009 3.574            3.574


La les deux premiers champs sont les champs de jointure avec le premier fichier. Il faut savoir que les lignes ne sont pas en face de l'autre fichier en cas de paste. Il faut bien chercher sur les champs de jointure pour les assembler dans un troisième fichier et donc aussi éliminer les champs qui deviennent doublon comme le code_art et la campagne.  
 
Et voici la maquette finale ex :

Code :
  1. mag;code_art;campagne;st_juill;st_aout;st_sept;st_oct;st_nov­;st_dec;st_janv;st_fevr;st_mars;st_avril;st_mai;st_juin;pmaa­r_juill;pmaar_aout;pmaar_sept;pmaar_oct;pmaar_nov;pmaar_dec;­pmaar_janv;pmaar_fevr;pmaar_mars;pmaar_avril;pmaar_mai;pmaar­_juin;pmasr_juill;pmasr_aout;pmasr_sept;pmasr_oct;pmasr_nov;­pmasr_dec;pmasr_janv;pmasr_fevr;pmasr_mars;pmasr_avril;pmasr­_mai;pmasr_juin
  2. 206;00000176;2007;6.00;4.00;5.00;5.00;3.00;5.00;8.00;7.00;6.­00;10.00;10.00;10.00;2.146;2.146;2.146;2.195;2.195;2.229;2.2­29;2.229;2.229;2.229;2.229;2.228;2.146;2.146;2.146;2.195;2.1­95;2.229;2.229;2.229;2.229;2.229;2.229;2.228
  3. 206;00000176;2008;10.00;6.00;5.00;3.00;9.00;9.00;6.00;7.00;7­.00;;;;2.267;2.267;2.267;2.267;2.267;2.267;2.276;2.276;2.276­;0;0;0;2.267;2.267;2.267;2.267;2.267;2.267;2.276;2.276;2.276­;0;0;0
  4. 222;00061607;2007;;;;;2.00;2.00;2.00;2.00;2.00;2.00;2.00;2.0­0;8.48;8.475;8.476;8.477;8.479;8.479;8.479;8.479;8.479;8.479­;8.479;8.479;8.48;8.475;8.476;8.477;8.479;8.479;8.479;8.479;­8.479;8.479;8.479;8.479
  5. 222;00061607;2008;2.00;2.00;2.00;2.00;2.00;2.00;2.00;1.00;1.­00;;;;8.479;8.479;8.479;8.479;8.479;8.479;8.479;8.479;8.479;­0;0;0;8.479;8.479;8.479;8.479;8.47


 
J'ai bien réussi a faire cela en bash mais il me faut plus 48 heures pour réaliser le fichier final et c'est malheureusement impossible comme laps de temps.
 
J'espère que python pourra faire mieux que cela et que vous voudrez bien m'aider.
 
Merci d'avance
Lonewolf
 
ps : pour info, j'ai fais comme cela en bash  
 
# 1: Transformer code_art;campagne en code_art@camapagne, et trier le fichier numeriquement sur le champ 2

Code :
  1. sed -r -e 's/;[[:space:]]*$//' -e 's/^([^;]+);([^;]+);([^;]+);(.*)$/\1;\2@\3;\4/' D_STO2.CSV |sort -n -t ';' -k 2 > fic1.mod


 
# 1: Transformer code_art;campagne en code_art@camapagne, et trier le fichier numeriquement sur le champ 1

Code :
  1. sed -r 's/^([^;]+);([^;]+);(.*)$/\1@\2;\3/' D_PMA2.CSV |sort -n -t ';' -k 1 > fic2.mod


 
#3: Joindre les fichiers sur les champ 2 du fichier 1 et 1 du fichier2, remettre le champ mag à la bonne place, et separer le champ code_art@campagne en deux champ distincts

Code :
  1. join -1 2 -2 1 -t ';' fic1.mod fic2.mod | sed -r 's/^(.+)@([^;]+);([^;]+);(.*)$/\3;\1;\2;\4/' > STOCK.CSV


 
 

Reply

Marsh Posté le 12-08-2009 à 14:32:08   

Reply

Marsh Posté le 12-08-2009 à 14:54:32    

tu ne crois pas que tu aurais intérêt à mettre tout ca en bdd, dans deux tables, et ensuite à récupérer le résultat via une requête? ca te permettrait de bénéficier de la puissance d'un sgbd...

Reply

Marsh Posté le 12-08-2009 à 16:46:11    

Le souci est que j'ai plus de 400 000 lignes a entrer eventuellement dans la table. Ce qui fait environ 40 mo et que je ne peux integrer à la fois que 2mo.
 
Alors le souci est que je risque de passer plus d'heure à decouper puis integrer mon fichier, tout en sachant que le traitement se ferait tous les mois que d'avoir un script qui reprendrait tout à zero.
 
Amicalement
Lonewolf

Reply

Marsh Posté le 12-08-2009 à 17:12:07    

ok effectivement si c'est un traitement mensuel... mais je vois pas pourquoi tu pourrais pas charger 40mo en bdd... j'ai testé, en copiant tes 6 lignes d'exemples et en les dupliquant pour arriver à 800000 lignes (ce qui me fais un fichier de 50mo), mysql met 3 seconde seulement à les charger dans une table avec la requete suivante:

Code :
  1. LOAD DATA  INFILE 'd:\\data.csv'
  2. INTO TABLE mag
  3. FIELDS TERMINATED BY ' '
  4. IGNORE 1 LINES
 

alors je pense qu'il ya moyen... pas sur qu'avec python tu puisse faire aussi bien...

 


après dsl, mais en python je peux pas t'aider...

 


Message édité par pataluc le 12-08-2009 à 17:12:28
Reply

Marsh Posté le 13-08-2009 à 19:32:15    

On te retrouve de partout avec ta jointure... Steph70 !!!
 
Tu définis un dictionnaire

Code :
  1. dict={}


 
Tu traites le fichier 1.
Pour chaque ligne du fichier 1, tu extraits ce qui te servira de référence

Code :
  1. fp=open("fichier1", "r" )
  2. for ligne in fp:
  3.      ref=<routine d'extraction basée sur du ligne.split()>


 
Si ref n'est pas dans dict.keys(), ça veut dire que la ligne est nouvelle (pour le dictionnaire). Dans ce cas, tu la positionnes

Code :
  1. if ref not in dict.keys():
  2.      dict[ref]=ligne


Si ref est dans dict.keys(), ça veut dire que cette référence a déjà été insérée (théoriquement ça ne devrait jamais arriver mais bon...). Dans ce cas, à toi de gérer le cas...

Code :
  1. else:
  2.      ...<gestion intelligente>


Fin fichier 1

Code :
  1. fp.close()


 
Tu traites le fichier 2
Pour chaque ligne du fichier 2, tu extraits ce qui te servira de référence

Code :
  1. fp=open("fichier2", "r" )
  2. for ligne in fp:
  3.     ref=<routine d'extraction certainement identique à l'autre>


 
Si ref est dans dict.keys(), ça veut dire que cette référence a déjà été insérée à partir du fichier 1. Dans ce cas, tu la modifies

Code :
  1. if ref in dict.keys():
  2.     dict[ref]=<ajout de la ligne issue du fichier 2>


 
Si ref n'est pas dans dict.keys(), ça veut dire que la ligne du fichier 2 n'a pas de correspondance dans le fichier 1
Fin fichier 2

Code :
  1. fp.close()


 
En final, te suffit d'afficher dict.values()

Code :
  1. [print lig for lig in dict.values()]


 
Maintenant, avec 40Mo de data, peut-être que ça peut quand-même être trop. Dans ce cas, voir soluce pataluc. En plus, Python intègre en interne la bdd SQLite => http://www.jacquet80.eu/blog/post/ [...] 241-sqlite...


Message édité par Sve@r le 13-08-2009 à 19:42:17

---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
Reply

Marsh Posté le 22-08-2009 à 02:20:50    

c'est peanuts 40meg

Reply

Marsh Posté le 22-08-2009 à 10:54:49    

Taz a écrit :

c'est peanuts 40meg


Pas si tu bosses avec un Pentium 75 et 64Mo de RAM :o


---------------
Stick a parrot in a Call of Duty lobby, and you're gonna get a racist parrot. — Cody
Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed