staging.inyokaproject.org

bestimmte spalten löschen

Status: Ungelöst | Ubuntu-Version: Ubuntu 16.04 (Xenial Xerus)
Antworten |

oxidizer

Anmeldungsdatum:
29. Januar 2018

Beiträge: Zähle...

Hallo zusammen

Ich möchte aus einer Text Datei Spalten löschen, die keine Zahlen enthalten sondern zB. Text.

Mein Beispiel:

56	35	1	36	477	1	1
56	35	1	36	477	1	1
56	35	1	36	477	1	1
56	35	1	36	477	1	1
56	35	1	36	LNF	1	1
56	35	1	36	477	1	1
56	35	1	36	477	1	1
56	35	1	36	477	1	1
1	1	1	1	477	1	ASM
1	1	1	1	477	1	ASM
56	35	1	36	477	1	1
1	1	1	1	477	1	ASM
1	1	1	1	477	1	ASM
1	1	1	2	INF-479	1	6
1	1	1	1	477	1	1
5	2	1	1	INF-480	1	1
1	1	1	1	INF-481	1	1
1	1	1	1	477	1	1

Gewünschtes Ziel (alle Spalten löschen, die keine Zahlen enthalten) :

56	35	1	36	1
56	35	1	36	1
56	35	1	36	1
56	35	1	36	1
56	35	1	36	1
56	35	1	36	1
56	35	1	36	1
56	35	1	36	1
1	1	1	1	1
1	1	1	1	1
56	35	1	36	1
1	1	1	1	1
1	1	1	1	1
1	1	1	2	1
1	1	1	1	1
5	2	1	1	1
1	1	1	1	1
1	1	1	1	1

Gemeint ist nicht eine Lösung, wie "Lösche Spalte 5 und 7" mit cut etc. Meine Tabelle, die ich bearbeiten möchte ist wesentlich komplexer und mit über 2500 Spalten!

Könnte mir da jemand helfen? Vielen Dank

Doc_Symbiosis

Avatar von Doc_Symbiosis

Anmeldungsdatum:
11. Oktober 2006

Beiträge: 4212

Hm, das hier sollte Dir die zu löschenden Spalten ausgeben (die Datei habe ich mal test.txt genannt):

awk '{ for (t=1;t<=NF;t++) if ($t !~ /^[0-9]+$/) print t} ' test.txt | sort -u

seahawk1986

Anmeldungsdatum:
27. Oktober 2006

Beiträge: 10978

Wenn ich dich richtig verstehe, willst du sowas:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
#!/usr/bin/env python3
import fileinput
from collections import defaultdict

bad_columns = set()
columns = defaultdict(list)

for line in fileinput.input():
    fields = line.split()
    for column, field in enumerate(fields):
        if not column in bad_columns:
            if not field.replace('.', '').isdigit():  # adjust for your decimal separators
                bad_columns.add(column)
                columns.pop(column)
            else:
                columns[column].append(field)

for values in zip(*(v for c, v in sorted(columns.items()))):
    print(*values, sep='\t')

Das Skript nimmt entweder Datei(en) als Argument entgegen (in dem Fall fasst es sie zusammen) oder alternativ auch Daten über stdin (und funktioniert nur, solange alle Reihen die selbe Anzahl von mit Whitespace getrennten Feldern haben - wenn du das auf Tabs einschränken wolltest, müsste man in Zeile 9 line.rstrip('\n').split('\t') nutzen):

$ python3 filter_file.py data.tsv
56	35	1	36	1
56	35	1	36	1
56	35	1	36	1
56	35	1	36	1
56	35	1	36	1
56	35	1	36	1
56	35	1	36	1
56	35	1	36	1
1	1	1	1	1
1	1	1	1	1
56	35	1	36	1
1	1	1	1	1
1	1	1	1	1
1	1	1	2	1
1	1	1	1	1
5	2	1	1	1
1	1	1	1	1
1	1	1	1	1 

Die Ausgabe des Skripts kannst du dann einfach in eine Datei umleiten.

oxidizer

(Themenstarter)

Anmeldungsdatum:
29. Januar 2018

Beiträge: 9

@Doc_Symbiosis Ich habe mich mal an deine Version gehalten und bin auf ein weiteres Problem gestossen. Ich habe die Spaltenzahl in ein Array getan:

array=$(awk 'NR>1{ for (t=1;t<=NF;t++) if ($t !~ /^[0-9]+$/) print t}' data.tsv | sort -n -u)

und wollte mir dann anhand des array die ganzen Spalten anzeigen lassen mit:

for i in ${array[@]}; 
do awk '{print $i}' data.tsv > result.tsv;
done

Das Ergebnis ist, dass wieder alle Spalten aus der data.tsv in der result.tsv stehen. Ich versteh aber nicht wieso.

Doc_Symbiosis

Avatar von Doc_Symbiosis

Anmeldungsdatum:
11. Oktober 2006

Beiträge: 4212

Das Problem ist, dass die Variable $i in awk nicht bekannt ist. Das müsstest Du eher so machen:

for i in ${array[@]}; do awk -v col="$i" '{print $col}' data.tsv >> result.tsv; done 

Und bei der Umleitung musst Du >> verwenden, denn sonst hast Du nur den Inhalt der letzen Spalte in result.tsv stehen...

oxidizer

(Themenstarter)

Anmeldungsdatum:
29. Januar 2018

Beiträge: 9

Super, vielen Dank. Hatte ich schon wieder vergessen, dass ich awk sagen muss, dass es sich um eine Variable handelt. Aber ist es nicht so, dass ich mit ">>" die Ergebnisse untereinander weg schreiben lassen? Ginge das auch, dass ich die Spalten dann auch wieder als Spalten in Form einer Tabelle ausgeben lassen könnte?

Doc_Symbiosis

Avatar von Doc_Symbiosis

Anmeldungsdatum:
11. Oktober 2006

Beiträge: 4212

Hm, ich dachte, Du willst die Spalten löschen? Warum willst Du sie denn nochmal in eine extra-Datei schreiben?

oxidizer

(Themenstarter)

Anmeldungsdatum:
29. Januar 2018

Beiträge: 9

Weil sich hier das Vorgehen etwas anders entwickelt hatte, als ich dachte. Anfangs dachte ich, es wäre möglich die Spalten mit Buchstaben raus zu löschen und den Rest neu in eine Datei schreiben zu lassen. Es entwickelte sich aber so, dass ich die Spalten mit Buchstaben rausschreiben lasse und ich die Spalten wieder als Spalten schreiben lassen kann, brauch ich nur die Zeile

for i in ${array[@]}; do awk -v col="$i" '{print $col}' data.tsv >> result.tsv; done

entsprechend entgegen gesetzt umschreiben müsste.

Weisst du was ich meine? Es tut mir leid, wenn ich mich nicht verständlich ausgedrückt habe.

Doc_Symbiosis

Avatar von Doc_Symbiosis

Anmeldungsdatum:
11. Oktober 2006

Beiträge: 4212

Hm, so ganz verstehe ich Dich leider nicht. Also so ginge es, falls Dir die Spaltentrenner egal sind:

columns=$(awk '{ for (t=1;t<=NF;t++) if ($t !~ /^[0-9]+$/) print t}' test.txt | sort -u)
cut --complement -f $(echo $columns |sed 's/ /,/') --output-delimiter=" " test.txt # Alle Spalten, die keine Buchstaben enthalten
cut  -f $(echo $columns |sed 's/ /,/') --output-delimiter=" " test.txt # Alle Spalten, die Buchstaben enthalten
Antworten |