Tengo un archivo de datos A.tsv
(separador de campo = \t
):
id mutation
243 siti,toto,mumu
254
267 lala,siti,sojo
289 lala
y un archivo de plantilla B.txt
(separador de campo = no importante porque solo una línea y una columna):
lala,siti,mumu
Quiero crear una nueva columna en A.tsv
(pero en un nuevo archivo C.tsv
) llamada mutation_not
donde se imprimen solo las mutaciones presentes en la mutation
columna A.tsv
que no están presentes en la lista de B.txt
.
C.tsv
Se ve como esto:
id mutation mutation_not
243 siti,toto,mumu toto
254
267 lala,siti,sojo sojo
289 lala
Probé con excluir:
awk 'NR==FNR {exclude[$0];next} !($0 in exclude)' file2 file1
pero no tengo ningún buen resultado. ¿Tienes una idea? Gracias
Respuesta1
awk ' BEGIN{OFS="\t"}
NR==FNR{ for(i=1; i<=NF; i++) muts[$i]; next }
FNR>1 { len=split($2, tmp, ",");
for(i=1; i<=len; i++) buf= buf (tmp[i] in muts?"":(buf==""?"":",") tmp[i])
}
{ print $0, (FNR==1?"mutation_not":buf); buf="" }' FS=',' fileB FS='\t' fileA
Respuesta2
Usando gawk
:
awk 'BEGIN{OFS="\t"; }
NR==FNR{ar[$1]=$1;next}
FNR==1{$(NF+1) = "mutation_not"}
FNR>1{split($2,a,",");
for(i in a) if (a[i] in ar) ;
else ncol[$1] = (ncol[$1])? ncol[$1] "," a[i] : a[i];
$(NF+1) = ncol[$1]}1'
RS="," B.txt RS="\n" FS="\t" A.tsv
Suponiendo que todos los campos están separados por comas y tienen solo una línea, el Separador de registros( RS
) se establece en coma para el archivo B.txt
.
NR==FNR{ar[$1]=$1;next
crea una matriz ar
indexada en el primer campo del primer archivo.
FNR==1{$(NF+1) = "mutation_not"
crea una columna más en el nombre del encabezado.
FNR>1{split($2,a,",")
divide el segundo campo de A.tsv
una matriz a
.
La siguiente entrada que no está presente B.txt
se guarda en la ncol
matriz.
$(NF+1) = ncol[$1]
crea una columna más con elementos de matriz ncol
.
Respuesta3
Formaremos un set
s2 a partir de los elementos separados por comas del archivo B.txt.
Luego, para cada línea de A.tsv convertiremos el segundo campo en un conjunto y le restaremos el conjunto s2. Esto nos proporciona las mutaciones presentes en A.tsv que no se encuentran en B.txt. Luego unimos los elementos resultantes y lo imprimimos junto con la línea original.
python3 -c 'import sys
tsv,txt = sys.argv[1:]
fs,rs = "\t","\n"
ofs,dlm = fs,","
with open(txt) as fh, open(tsv) as f:
s2 = set(*list(map(lambda x:x.rstrip(rs).split(dlm),fh.readlines())))
for nr,ln in enumerate(f,1):
l = ln.rstrip(rs)
if nr == 1: print(l,"mutation_not",sep=ofs)
else:
F = l.split(ofs)
if len(F) < 2: print(l)
else: print(l,
dlm.join({*F[1].split(dlm)}-s2),sep=ofs)
' A.tsv B.txt
Resultado:
id mutation mutation_not
243 siti,toto,mumu toto
254
267 lala,siti,sojo sojo
289 lala
Esta vez usaremos el editor Gnu sed para obtener los resultados:
sed -Ee '
1{h;d;}
2s/\tmutation$/&&_not/;t
s/\t\S+$/&&,/;T;G
s/\t/\n/2;ta
:a
s/\n([^,]+),(.*\n(.*,)?\1(,|$))/\n\2/;ta
s/\n([^,\n]+),/\t\1\n/;ta
s/\n.*//
' B.txt A.tsv
La idea es que el archivo Btxt se almacena en espera (suponiendo que sea una línea) y a cada línea de A.tsv se le agrega el contenido de B.txt y se marcan las mutaciones que se encuentran en B.txt. Después de observar todas las mutaciones, se imprime la línea.