J'ai un tableau numérique, c'est-à-dire que toutes les cellules ont des nombres. Il s'agit d'un file délimité par des tabulations, avec des en-têtes et des noms de ligne non numériques. J'ai besoin de supprimer toutes les colonnes qui ajoutent zéro. Je voudrais garder la première colonne (noms de lignes), et les en-têtes des autres colonnes qui n'ont pas été supprimées.
Consortingbution
abcd e 1 2 0 f 3 4 0 g 5 6 0
Sortie
abc e 1 2 f 3 4 g 5 6
Problème analogue mais avec des lignes: supprimer les lignes qui sum à zéro
awk solution serait génial; Je veux éviter de charger d'énormes files dans R.
enlever la colonne
c.awk:
{ for(i=1;i<=NF;i++) { line[NR][i]=$i ; col[i]+=$i ;} } END { for ( l=1 ; l<=NR ; l++ ) { printf line[l][1] "\t" ; for (c=2;c<=NF;c++) if (col[c]) printf line[l][c] "\t" ; printf "\n" ; } }
où
{ for(i=1;i<=NF;i++) { line[NR][i]=$i ; col[i]+=$i ;} }
{ for(i=1;i<=NF;i++) { line[NR][i]=$i ; col[i]+=$i ;} }
stocke toutes les lignes (y compris les noms de colonnes). END
clause END
imprime toutes les colonnes si count! = 0. tester:
awk -f c.awk a abc e 1 2 f 3 4 g 5 6
pour la solution en ligne …
essayer
awk 'NR==1 {print } NR>1 { s=0 ; for(i=1;i<=NF;i++) s+=$i ; if (s) print ;}'
où
NR==1 {print }
tête d'printing NR>1 { s=0 ; for(i=1;i<=NF;i++) s+=$i ; if (s) print ;}
NR>1 { s=0 ; for(i=1;i<=NF;i++) s+=$i ; if (s) print ;}
teste pour 0 et imprime si non i=2
si la première colonne est le nom de la ligne. notez que cela va afficher les lignes, pas supprimer du file d'origine.
Il peut être plus facile avec perl
si vous voulez garder l'espacement:
perl -lne ' $i = 0; for (/\S+\s*/g) { $cell[$.][$i] = $_; $sum[$i++] += $_ } END{ @keep=(0, grep {$sum[$_]} (1..$#sum)); print((@{$cell[$_]})[@keep]) for (1..$.) }'
Cela charge tout le file en memory. Pour éviter cela, vous aurez besoin de deux passes dans le file.
Cela pourrait être fait avec une combinaison de awk
et sed
:
awk ' NR>1{for (i=2; i<=NF; i++) sum[i]+=$i; if (NF>n) n = NF} END { for (;n>1;n--) if (!sum[n]) print "s/[^[:blank:]]\\{1,\\}[[:blank:]]*//" n }' < file | sed -f - file
awk
générant le script sed
pour supprimer les colonnes dont la sum est 0. Les commands sed
s/[^[:blank:]]\{1,\}[[:blank:]]*//3
supprimeraient les colonnes tout en préservant l'espacement des autres colonnes, mais serait assez cher, vous voudrez peut-être faire ce ssortingpping en perl
si la performance est un problème.
Pour les lignes, c'est beaucoup plus facile:
perl -MList::Util=sum -lane 'print if $. == 1 or sum @F'
Comme ces valeurs sont toujours des entiers, vous pouvez faire quelque chose comme:
cut $(awk 'NR>1{for(i=2;i<=NF;i++) s[i]+=$i}END{printf("%s", "-f 1"); for (i=2;i<=NF;i++) {if (s[i]) printf(",%s", i)}}' infile) infile
cela lit le file deux fois: awk
obtient les numéros de colonne où la sum n'est pas nulle; ceux-ci sont ensuite utilisés avec la cut
pour imprimer uniquement les colonnes souhaitées.