J'ai un grand nombre de répertoires de fichiers délimités par des tabulations txt avec plusieurs lignes et colonnes, par exemple
NewFile Variant Nº of repeated Location c.B481A:p.G861S 2 File1,File2 c.C221C:p.D461W 1 File1 c.G31T:p.G61R 1 File1 c.C21C:p.D61W 1 File2 c.G1T:p.G1R 1 File2
File2 Id Sample Time ... Variant[Colummn16] ... 1 s1 t0 c.B481A:p.G861S 2 s2 t2 c.C21C:p.D61W 3 s5 t1 c.G1T:p.G1R
et ce que je cherche est de créer un nouveau fichier avec:
i.e.:
File1 Id Sample Time ... Variant[Colummn16] ... 1 s1 t0 c.B481A:p.G861S 2 s2 t2 c.C221C:p.D461W 3 s5 t1 c.G31T:p.G61R
Je pense qu'en utilisant un script basique dans bash avec awk sort et uniq cela fonctionnera, mais je ne sais pas par où commencer. Ou si utiliser Rstudio ou python (3) est plus facile, je pourrais essayer.
Merci !!
3 Réponses :
Je suppose qu'il existe une solution python ou bash plus concise, mais voici une solution R relativement simple qui utilise des fonctions tidyverse (bien que vous puissiez la répliquer dans data.table ou base R si tu voulais). Pour l'exemple, j'ai téléchargé vos données dans mon répertoire de travail mais je vous déconseille de vous fier à votre répertoire de travail en R (ici, il est cependant reproductible :)). Comme le note Gregor, vous pouvez consulter le package ici ou utiliser projects , ou vous pouvez utiliser des chemins absolus si vous ne vous inquiétez pas de la portabilité à des collègues en dehors de votre système.
Bien sûr, à partir de là, vous pouvez nettoyer la sortie pour qu'elle ressemble exactement à ce que vous voulez. J'ai également utilisé readr :: read_csv () pour l'exemple, mais vous voudrez probablement utiliser readr :: read_delim () avec delim = "\ t " ou utilisez simplement data.table :: fread () .
Solution
library(readr) File1 <- read.table(header = T, text = "Id Sample Time Variant[Colummn16] 1 s1 t0 c.B481A:p.G861S 2 s2 t2 c.C221C:p.D461W 3 s5 t1 c.G31T:p.G61R") File2 <- read.table(header = T, text = "Id Sample Time Variant[Colummn16] 1 s1 t0 c.B481A:p.G861S 2 s2 t2 c.C21C:p.D61W 3 s5 t1 c.G1T:p.G1R") write_csv(File1, "File1.csv") write_csv(File2, "File2.csv")
Données (et enregistrement dans wd):
library(dplyr)
# Get the file paths
file_paths <- list.files(pattern = "File\\d", full.names = T)
# Use the paths to read the data into a list (sapply retains the names)
list_of_files <- sapply(file_paths, read_csv, simplify = F)
# Create a data.frame from your list
df <- bind_rows(list_of_files, .id = "Location")
# Summarising the variables by grouping by the variant and counting & concatenating
df %>%
mutate(Location = gsub(".*?/([[:alnum:]]+).*", "\\1", Location)) %>% #using regex to simplify file name
group_by(Variant.Colummn16.) %>%
summarise(n = n(),
Location = paste0(Location, collapse = ", "))
# A tibble: 5 x 3
Variant.Colummn16. n Location
<chr> <int> <chr>
1 c.B481A:p.G861S 2 File1, File2
2 c.C21C:p.D61W 1 File2
3 c.C221C:p.D461W 1 File1
4 c.G1T:p.G1R 1 File2
5 c.G31T:p.G61R 1 File1
Woo merci, je vais l'essayer, mais dois-je changer sapply (file_paths, read_csv, simplify = F) par sapply (file_paths, read_txt, simplify = F) , si J'ai un fichier txt, non?
@WindSur, je ne pense pas que readr ait une fonction read_txt , mais read_delim avec delim = "\ t" , ou read_table2 peut convenir à vos besoins (pas sûr de la structure exacte de vos fichiers).
Une simple bash serait difficile, je pense, mais tout le monde a du mal à traîner: D
awk 'FNR==1{next}
{
++n[$16];
if ($16 in a) {
a[$16]=a[$16]","ARGV[ARGIND]
}else{
a[$16]=ARGV[ARGIND]
}
}
END{
printf("%-24s %6s %s\n","Variant","Nº","Location");
for (v in n) printf("%-24s %6d %s\n",v,n[v],a[v])}' *
C'est ce que je recherche, mais je ne sais pas pourquoi il m'imprime également une ligne avec un numéro et non avec la variante
@WindSur si les fichiers sont exactement comme vous l'avez dit, cela ne devrait pas arriver et je l'ai testé. Il se peut cependant qu'il y ait des lignes vides ou des lignes avec une variante manquante ou des lignes d'un format totalement différent. Si les lignes ne sont en fait séparées que par des tabulations et jamais par des espaces, vous devez utiliser awk -FS = '\ t' . Pour voir s'il y a des lignes vides, utilisez awk '/ ^ $ {print ARGV [ARGIND], FNR}' * , mieux encore vous devriez télécharger deux fichiers afin que nous puissions reproduire le comportement.
J'ai essayé, mais je n'ai rien vu ici certains fichiers: lien < / a> Dans ce cas, la colonne variante est la 10ème position ou la 9ème si nous partons de 0
Si vos fichiers contiennent la variante de la colonne 10, vous devrez remplacer 16 $ par 10 $. awk 'FNR == 1 {suivant} {++ n [$ 10]; if ($ 10 in a) {a [$ 10] = a [$ 10] "," ARGV [ARGIND]} else {a [$ 10] = ARGV [ARGIND]}} END { printf ("% - 24s% 6s% s \ n", "Variante", "Nº", "Location"); pour (v en n) printf ("% - 24s % 6d% s \ n ", v, n [v], a [v])} '*
Oui, bien sûr que je l'ai fait, mais cela ne fonctionne pas avec ces fichiers. Tous les fichiers sont délimités par tabulation, donc j'ai écrit awk '-fs =' \ t '{++ n [10 $]; si (10 $ dans A) {A [10 $] = a [$] "", " Argv [argind]} else {A [10 $] = argv [argind]}} fin {printf ("% - 24s% 6s% s \ n", "variante", "nº", "emplacement"); pour (V In n) Printf ("% - 24S% 6D% S \ N", V, N [V], A [V])} '* code>? mais ne fonctionne pas
@WindSur awk -F '\ t' 'FNR == 1 {suivant} {++ n [$ 10]; if ($ 10 in a) {a [$ 10] = a [$ 10] "," ARGV [ARGIND ]} else {a [$ 10] = ARGV [ARGIND]}} END { printf ("% - 24s% 6s% s \ n", "Variant", "Nº", "Location"); pour (v dans n) printf ("% - 24s% 6d% s \ n", v, n [v], a [v])} '*
Pure bash. Nécessite la version 4.0+
c.B481A:p.G861S 2 File1,File2 c.G1T:p.G1R 1 File2 c.C221C:p.D461W 1 File1 c.G31T:p.G61R 1 File1 c.C21C:p.D61W 1 File2
sorties
# two associative arrays
declare -A files
declare -A count
# use a glob pattern that matches your files
for f in File{1,2}; do
{
read header
while read -ra fields; do
variant=${fields[3]} # use index "15" for 16th column
(( count[$variant] += 1 ))
files[$variant]+=",$f"
done
} < "$f"
done
for variant in "${!count[@]}"; do
printf "%s\t%d\t%s\n" "$variant" "${count[$variant]}" "${files[$variant]#,}"
done
L'ordre des lignes de sortie est indéterminé: les tableaux associatifs n'ont pas d'ordre particulier. P >
Génial! Mais je ne connais pas les premières lignes, déclarer -a code>, devrais-je écrire le chemin là-bas? Et si j'ai plus de 2 fichiers?
@WindSur Vous récupérez vos fichiers en utilisant le motif File {1,2} à la ligne 6, donc dans votre cas, cela pourrait simplement être * ou * .txt < / code>.
Je ne suis pas sûr de la colonne 3 (en tant que ligne simple, bien que vous puissiez trouver un moyen de le faire, j'en suis sûr) Quelque chose comme ça pourrait fonctionner: stackoverflow.com/questions/25652252/... Pour 1 et 2, vous pouvez utiliser:
awk '{print $ 4}' file1.txt> shared.txtetawk '{print $ 4}' file2.txt >> shared.txtpuissort shared.txt | uniq -c