Agregar columna de un archivo .csv a otro archivo .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 deseado

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

He intentado usar "unirse" y "pegar" en vano. ¿Hay un comando bash para hacer esto? La columna "A" es la misma en ambos .csvarchivos.

Roboman1723
fuente
Entonces, ¿está solicitando copiar la columna B al archivo 1? ¿O las columnas C y D al archivo2?
Tim
De cualquier manera estaría bien siempre que el resultado coincida con "deseadoOutput.csv"
Roboman1723
He agregado una nueva respuesta que, creo, es más fácil que todas las otras respuestas (incluida mi primera respuesta). Es posible que desee considerar aceptar eso para que, para referencia futura, la información se encuentre fácilmente.
don.joey

Respuestas:

11

Con solo awkcomando:

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

Obtenga una línea del archivo1 y almacénela en una variable local f1, luego imprima la línea que se almacenó f1y finalmente imprima los campos tercer ( $3) y adelante ( $3) del archivo1 que se delimitaron con una coma por ,completo, y cambie el OFS (separador de campo de salida [espacio por predeterminado]) a coma ( ,).


El comando corto sería así:

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

pegue el archivo2, luego corte y pegue la tercera columna a la siguiente ( -f3-) del archivo1.


Con awky paste(opción A)

El siguiente comando también copia las dos últimas columnas ( C,D) del archivo1 al final de cada línea en el archivo2:

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

El comando anterior pega el contenido del archivo2, luego imprime un delimitador de coma ( -d',') y luego pega los dos últimos campos ( NFes el índice del último campo y $NFes la cadena que es su índice NF. Así $(NF-1)es el segundo campo antes del último campo) del archivo1 cuando ese índice redefine o se divide con el espectador de coma ( -F',').

Con awky paste(opción B)

Este comando también es el mismo que el anterior ( $3y $4apunta al tercer y cuarto campo de cada línea del archivo1):

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

O otra solución con cutcomando:

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

el comando cortar en el comando anterior primero corta el primer campo ( -f1que está indexado con el delimitador de coma ( -d.)) del archivo1 ( cut -d, -f1 file1), luego corta y pega el segundo campo del archivo2 ( cut -d, -f2 file2) y finalmente corta y pega la tercera columna ( -f3) a los siguientes ( -) del archivo1 ( cut -d, -f3- file1) nuevamente.

Este comando también devuelve el mismo resultado:

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

pegue el segundo campo del archivo1 ( awk -F',' '{print $1}' file1) luego imprima una coma ( -d,), luego pegue la segunda columna del archivo2 ( awk -F',' '{print $2}' file2), finalmente pegue la segunda y última columna del archivo1 ( awk -F',' '{print $3","$4}' file1) nuevamente.

αғsнιη
fuente
@kasi podrías hacer esto a través de awk mismo. Ver stackoverflow.com/a/14984673/3297613
Avinash Raj el
9

Aquí hay una belleza (creo):

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

Desglosado en pasos:

Paso 1. Instale csvkit:

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

Paso 2. Use el comando de unión con una coma como separador

join -t,

Paso 3. Aliméntalo con las columnas reales que deseas. Observe cómo alimenta la primera columna dos veces, porque esa es en la que se realiza la unión (comportamiento predeterminado de join).

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

o en taquigrafía:

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

Si lo desea, puede redirigir esa salida estándar a un archivo (salida deseada).

Ventajas

Este método tiene varias ventajas sobre los otros propuestos.

Primero y principal: realiza una unión real. Eso significa que también se puede usar para datos más complejos. Es muy fácil hacer una unión en otro campo, por ejemplo. No solo mira la posición del campo, sino que realmente toma en cuenta la columna. Realmente funciona con el formato de los datos (csv) y no lo trata como texto.

En segundo lugar, utiliza el potente kit de herramientas csv que también le permite a) mostrar estadísticas con un comando ( csvstats), b) verificar si los datos están limpios ( csvclean), pero también transformarlos en json, en sql, o incluso cargarlos en ¡pitón! Este kit de herramientas se usa mucho en ciencia de datos para la preparación de datos.

don.joey
fuente
Si está instalando en Ubuntu, es posible que deba instalar los encabezados de desarrollo de Python antes de instalar csvkit: sudo apt-get install python-dev python-pip python-setuptools build-essential- enlace
karel
Impresionante respuesta también, estoy trabajando en un servidor de la empresa, por lo que instalar cosas requiere aproximadamente una semana de papeleo. ¡Sin embargo, funciona en mi máquina!
Roboman1723
+1 por mostrarme otra herramienta para datos CSV. Pregunta separada, pero ¿conoce a un redactor de informes independiente para archivos de datos CSV?
Joe
@ Joe, ¿puedes ser más específico sobre lo que quieres decir cuando hablas de un 'redactor de informes'? No estoy seguro de entender lo que quieres decir.
don.joey
Publiqué
Joe
7

Aquí hay otro hermoso. Creo que es la más fácil de todas las sugerencias, hasta ahora.

csvtool pastecol 2 2 file1.csv file2.csv

Si no ha instalado csvtool ya en el pasado, debe hacerlo sudo apt-get install csvtool.

De los documentos:

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

Reemplace el contenido de las columnas a las que se hace referencia en el archivo input.csv con el de la columna correspondiente especificada en update.csv.

Ejemplo:

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

Tenga en cuenta cómo en nuestro caso estamos reemplazando las segundas columnas de los archivos.

Ejemplos

file1.csv

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

file2.csv

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

Combinando los dos archivos:

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

Lo que esencialmente hacer es pegar la columna dos de file2.csvque la columna 2 en file1.csv.

Tenga en cuenta que esto también funciona en el mismo documento. Si desea intercambiar dos columnas, puede hacerlo utilizando el mismo archivo que input.csv y update.vsc.

csvtool pastecol 2 1 file2.csv file2.csv 
A,A
A,A
A,A 
A,A
don.joey
fuente
Sin duda el más elegante.
Jacob Vlijm
2

Para mover un número elegido de columnas de un archivo a otro:

#!/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:]))

de dos archivos:

archivo_1

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

archivo_2

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

Cuando configuras cols = 1:

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

Pero cuando configuras 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

Cómo utilizar

Copiarlo en un archivo vacío, establecer la ruta a file1, file2y el número de columnas a mover, guardar como move.pyy ejecutarlo por:

python3 /path/to/move.py

También es posible agregar una o más columnas desde el medio de las columnas del archivo fuente de esta manera.

Jacob Vlijm
fuente
Sin import csvembargo, me hubiera encantado verte usar .
don.joey
@ don.joey Gracias por la sugerencia, definitivamente lo investigaremos.
Jacob Vlijm
0

Otro método en python a través del módulo 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))

Para ejecutar el script anterior,

python3 script.py file1 file2

Salida:

A,B,C,D
A,B,C,D
A,B,C,D
A,B,C,D
Avinash Raj
fuente