Ajouter une colonne d'un fichier .csv à un autre fichier .csv

12

file1.csv

A,,C,D
A,,C,D
A,,C,D
A,,C,D

file2.csv

A,B
A,B
A,B
A,B

Output.csv souhaité

A,B,C,D
A,B,C,D
A,B,C,D
A,B,C,D

J'ai essayé d'utiliser "join" et "paste" en vain. Existe-t-il une commande bash pour ce faire? La colonne "A" est la même dans les deux .csvfichiers.

Roboman1723
la source
Vous demandez donc de copier la colonne B dans le fichier 1? Ou les colonnes C et D dans file2?
Tim
Dans les deux cas, ce serait bien tant que la sortie correspond à "desireOutput.csv"
Roboman1723
J'ai ajouté une nouvelle réponse qui, je pense, est plus facile que toutes les autres réponses (ma première réponse incluse). Vous voudrez peut-être envisager d'accepter cela afin que, pour référence future, les informations soient facilement trouvées.
don.joey

Réponses:

11

Avec une seule awkcommande:

awk -F, '{getline f1 <"file2" ;print f1,$3,$4}' OFS=, file1

Obtenez une ligne à partir de file1 et stockez-la dans une variable locale f1, puis imprimez la ligne qui a stocké dans f1et enfin imprimez les troisième ( $3) et quatrième ( $3) champs du fichier1 qui ont délimité ,complètement par une virgule , et changez l'OFS (séparateur de champ de sortie [espace par par défaut]) en virgule ( ,).


La commande courte serait comme ceci:

paste -d, file2 <(cut -d, -f3- file1)
 A B C D  
 A B C D  
 A B C D  
 A B C D  

collez le fichier2, puis coupez et collez la troisième colonne à la suivante ( -f3-) du fichier1.


Avec awket paste(option A)

La commande ci-dessous copie également les deux dernières colonnes ( C,D) du fichier1 à la fin de chaque ligne du fichier2:

paste -d',' file2  <(awk -F',' '{print $(NF-1)","$NF}' file1)

Au-dessus de la commande, collez le contenu du fichier2, puis imprimez un délimiteur de virgule ( -d','), puis collez les deux derniers champs ( NFest l'index du dernier champ et $NFla chaîne dont est l'index NF. Il en $(NF-1)est de même du deuxième champ avant le dernier champ) de file1 lorsque cet index redéfinit ou se sépare avec une virgule spectateur ( -F',').

Avec awket paste(option B)

Cette commande est également la même que ci-dessus ( $3et $4pointe vers le troisième et le quatrième champ de chaque ligne du fichier1):

paste -d',' file2  <(awk -F',' '{print $3","$4}' file1)

Ou une autre solution avec cutcommande:

paste -d, <(cut -d, -f1 file1) <(cut -d, -f2 file2) <(cut -d, -f3- file1)

couper la commande de la commande ci-dessus couper d'abord le premier champ ( -f1indexé avec un délimiteur de virgule ( -d.)) de file1 ( cut -d, -f1 file1), puis couper et coller le deuxième champ de file2 ( cut -d, -f2 file2) et enfin couper et coller la troisième colonne ( -f3) dans les nexts ( -) à partir de file1 ( cut -d, -f3- file1) à nouveau.

Cette commande renvoie également le même résultat:

paste -d, <(awk -F',' '{print $1}' file1) <(awk -F',' '{print $2}' file2) <(awk -F',' '{print $3","$4}' file1)

collez le deuxième champ de file1 ( awk -F',' '{print $1}' file1) puis imprimez une virgule ( -d,), puis collez la deuxième colonne de file2 ( awk -F',' '{print $2}' file2), puis collez à nouveau la deuxième et la dernière colonne de file1 ( awk -F',' '{print $3","$4}' file1).

αғsнιη
la source
@kasi, vous pouvez le faire via awk lui-même. Voir stackoverflow.com/a/14984673/3297613
Avinash Raj
9

Voici une beauté (je pense):

join -t, <(csvcut -c 1,3,4 file1.csv) <(csvcut -c 1,2 file2.csv)

Décomposé en étapes:

Étape 1. Installez csvkit:

sudo pip install csvkit
sudo apt-get install python-dev python-pip python-setuptools build-essential

Étape 2. Utilisez la commande join avec une virgule comme séparateur

join -t,

Étape 3. Donnez-lui les colonnes que vous souhaitez. Notez comment vous l'alimentez deux fois dans la première colonne, car c'est celle sur laquelle la jointure est réellement effectuée (comportement par défaut de join).

join -t, <(csvcut --columns 1,3,4 file1.csv) <(csvcut --columns 1,2 file2.csv)

ou en sténographie:

join -t, <(csvcut -c 1,3,4 file1.csv) <(csvcut -c 1,2 file2.csv)

Vous pouvez rediriger cette sortie standard vers un fichier (désiréOutput) si vous le souhaitez.

Les avantages

Cette méthode présente plusieurs avantages par rapport aux autres proposées.

D'abord et avant tout: il réalise une véritable jointure. Cela signifie qu'il peut également être utilisé pour des données plus complexes. Par exemple, il est très facile de faire une jointure sur un autre domaine. Il ne regarde pas simplement la position du champ, mais il tient vraiment compte de la colonne. Il fonctionne en fait avec le format des données (csv) et ne le traite pas comme du texte.

Deuxièmement, il utilise la boîte à outils csv très puissante qui vous permet également a) d'afficher des statistiques avec une seule commande ( csvstats), b) de vérifier si les données sont propres ( csvclean), mais aussi de les transformer en json, en sql, ou même de les charger dans python! Cette boîte à outils est largement utilisée en science des données pour la préparation des données.

don.joey
la source
Si vous installez sur Ubuntu, vous devrez peut-être installer les en-têtes de développement Python avant d'installer csvkit: sudo apt-get install python-dev python-pip python-setuptools build-essential- lien
karel
Réponse géniale aussi, je travaille sur un serveur d'entreprise, donc l'installation de trucs prend environ une semaine de paperasse. Fonctionne sur ma machine cependant!
Roboman1723
+1 pour me montrer un autre outil pour les données CSV. Question distincte, mais connaissez-vous un rédacteur de rapport autonome pour les fichiers de données CSV?
Joe
@Joe, pouvez-vous être plus précis sur ce que vous voulez dire lorsque vous parlez d'un «rédacteur de rapport»? Je ne suis pas sûr de comprendre ce que vous voulez dire.
don.joey
J'ai posté une question distincte sur unix.stackexchange.com/questions/170199/…
Joe
7

En voici une autre magnifique. Je pense que c'est la plus simple de toutes les suggestions jusqu'à présent.

csvtool pastecol 2 2 file1.csv file2.csv

Si vous n'avez pas déjà installé csvtool dans le passé, vous devez le faire sudo apt-get install csvtool.

De la documentation:

pastecol <column-spec1> <column-spec2> input.csv update.csv

Remplacez le contenu des colonnes référencées par dans le fichier input.csv par celui de la colonne correspondante spécifiée par dans update.csv.

Exemple:

  csvtool pastecol 2-3 1- input.csv update.csv.csv > output.csv

Notez comment, dans notre cas, nous remplaçons les secondes colonnes des fichiers.

Exemples

file1.csv

A,,C,D
A,,C,D
A,,C,D
A,,C,D

file2.csv

A,B
A,B
A,B
A,B

Combiner les deux fichiers:

csvtool pastecol 2 2 file1.csv file2.csv
A,B,C,D
A,B,C,D
A,B,C,D
A,B,C,D

Ce que vous faites essentiellement est de coller la deuxième file2.csvcolonne comme colonne 2 file1.csv.

Notez que cela fonctionne également sur le même document. Si vous souhaitez échanger deux colonnes, vous pouvez le faire en utilisant le même fichier que input.csv et update.vsc.

csvtool pastecol 2 1 file2.csv file2.csv 
A,A
A,A
A,A 
A,A
don.joey
la source
Sans doute le plus élégant.
Jacob Vlijm
2

Pour déplacer un nombre choisi de colonnes d'un fichier à un autre:

#!/usr/bin/env python3

cols = 1; file_1 = "/path/to/file_1"; file_2 = "/path/to/file_2"

def readfile(file):
      with open(file) as src:
          return [item.strip().split(",") for item in src.readlines()]

file_1 = readfile(file_1); file_2 = readfile(file_2)

for i in range(len(file_1)):
    print((",").join(file_1[i]+file_2[i][-cols:]))

à partir de deux fichiers:

fichier_1

A,B
A,B
A,B
A,B

file_2

K,L,M
K,L,M
K,L,M
K,L,M

Lorsque vous définissez cols = 1:

A,B,M
A,B,M
A,B,M
A,B,M

Mais lorsque vous définissez cols = 2:

A,B,L,M
A,B,L,M
A,B,L,M
A,B,L,M

cols = 3:

A,B,K,L,M
A,B,K,L,M
A,B,K,L,M
A,B,K,L,M

Comment utiliser

Copier dans un fichier vide, définissez le chemin d'accès file1, file2et le nombre de colonnes pour se déplacer, l' enregistrer comme move.pyet l' exécuter par:

python3 /path/to/move.py

Il est également possible d'ajouter une ou plusieurs colonnes à partir du milieu des colonnes du fichier source de cette façon.

Jacob Vlijm
la source
J'aurais bien aimé vous voir utiliser import csv.
don.joey
@ don.joey Merci pour la suggestion, je vais certainement y réfléchir.
Jacob Vlijm
0

Une autre méthode en python via le module csv.

script.py

#!/usr/bin/python3
import csv
import sys
file1 = sys.argv[1]
file2 = sys.argv[2]
with open(file2, 'r') as r:
    with open(file1, 'r') as f:
        csv_f = csv.reader(f)
        csv_r = csv.reader(r)
        bar = [linex for linex in csv_r]
        foo = [liney[2:] for liney in csv_f]
        zipped = zip(bar,foo)
        result = [x+y for (x,y) in list(zipped)]
        for i in result:
            print(','.join(i))

Pour exécuter le script ci-dessus,

python3 script.py file1 file2

Production:

A,B,C,D
A,B,C,D
A,B,C,D
A,B,C,D
Avinash Raj
la source