[Python] Manipolare colonne e nome di un file.dat

Linguaggi di programmazione: php, perl, python, C, bash e tutti gli altri.
Avatar utente
vaeVictis
Imperturbabile Insigne
Imperturbabile Insigne
Messaggi: 4703
Iscrizione: venerdì 27 luglio 2012, 17:58
Desktop: Gnome
Distribuzione: Ubuntu 20.04 64bit

[Python] Manipolare colonne e nome di un file.dat

Messaggio da vaeVictis »

Ciao a tutti.
Come ho accennato nel titolo, mi capita spesso di dover manipolare il contenuto e il nome file.dat.

Per manipolazione del contenuto intendo quanto segue.
Il file.dat contiene un numero arbitrario di campi (che in quanto segue indico con $1, $2, ... $N) divisi da un separatore (generalmente uso il tab).
Mi trovo spesso a rielaborare questo tipo di contenuto, nel senso che (riga per riga) devo manipolare matematicamente i dati contenuti nelle varie colonne, con funzioni generiche, e riscriverli in un file che, a priori, contenga un numero di colonne anche differente dal numero di colonne da cui sono partito.
Per essere meno generici e più "matematici", devo prendere queste $1, $2, ... , $N e produrre un file con abbia come i-esima colonna una funzione nota solo al momento in cui lancio il programma.
Vorrei pertanto qualche suggerimento su come impostare la funzione print (python 3.x) in modo che "capisca" a run time le varie funzioni con cui rielaborare le colonne del file.dat e scrivere poi l'output.
Un'idea la ho, ma è un po' troppo complessa, quindi evito di scriverla per non confondere chi volesse aiutarmi.

Per manipolazione del nome di file.dat, intendo che il file di output avrà un nome ovviamente diverso da quello iniziale, ma che spesso è una "manipolazione" di quest'ultimo, in cui semplicemente aggiungo "qualcosa" che faccia capire il tipo di elaborazione fatta sulle colonne del file di partenza.
Anche per questo problema, avrei bisogno di qualche consiglio per muovermi in modo oculato (e come prima ho in mente alcune soluzioni che però sono un po' "complesse").

Vi ringrazio in anticipo per l'attenzione e per gli aiuti :ciao:
Pirates arrrrrrrrrrr awesome!!!
«I fear not the man who has practiced 10000 kicks once,
but I fear the man who has practiced one kick 10000 times.»
Nexol
Entusiasta Emergente
Entusiasta Emergente
Messaggi: 1169
Iscrizione: venerdì 13 novembre 2009, 10:15

Re: [Python] Manipolare colonne e nome di un file.dat

Messaggio da Nexol »

vaeVictis ha scritto:Il file.dat contiene un numero arbitrario di campi (che in quanto segue indico con $1, $2, ... $N) divisi da un separatore (generalmente uso il tab).
Un file csv. Se vuoi semplificarti la vita rivolgiti al modulo csv di Python.
vaeVictis ha scritto:e produrre un file con abbia come i-esima colonna una funzione nota solo al momento in cui lancio il programma.
Forse volevi dire "e produrre un file che abbia come i-esima colonna il risultato dell'elaborazione della colonna originale tramite una funzione nota solo al momento in cui lancio il programma.".
vaeVictis ha scritto:Vorrei pertanto qualche suggerimento su come impostare la funzione print (python 3.x) in modo che "capisca" a run time le varie funzioni con cui rielaborare le colonne del file.dat e scrivere poi l'output.
Print, o write? Vuoi stampare, o scrivere su un file?
vaeVictis ha scritto:Un'idea la ho, ma è un po' troppo complessa, quindi evito di scriverla per non confondere chi volesse aiutarmi.
Magari sei già sulla buona strada e si tratta solo di semplificare, se riporti la tua idea anche solo in pseudocodice, ci si può capire di più.

Per manipolazione del nome di file.dat, intendo che il file di output avrà un nome ovviamente diverso da quello iniziale, ma che spesso è una "manipolazione" di quest'ultimo, in cui semplicemente aggiungo "qualcosa" che faccia capire il tipo di elaborazione fatta sulle colonne del file di partenza.
Anche per questo problema, avrei bisogno di qualche consiglio per muovermi in modo oculato (e come prima ho in mente alcune soluzioni che però sono un po' "complesse").[/quote]

Idem come sopra, se le riporti magari si "semplificano".
Ubuntu 20.04 --> Notebook Dell 1747 - Intel Core i7-720QM - 8GB Ram - Scheda grafica AMD Mobility Radeon HD 4650 1GB Ram con driver radeon
Avatar utente
vaeVictis
Imperturbabile Insigne
Imperturbabile Insigne
Messaggi: 4703
Iscrizione: venerdì 27 luglio 2012, 17:58
Desktop: Gnome
Distribuzione: Ubuntu 20.04 64bit

Re: [Python] Manipolare colonne e nome di un file.dat

Messaggio da vaeVictis »

Ciao, grazie per l'interessamento.

Allora, in questi giorni ho dovuto lavorare anche su altre cose, ma, pensando a questo mio problema, mi sono reso conto che sto cercando di scrivere in Python un programma per la soluzione di un problema che si affronta facilmente con awk o altre utility del genere. E usando awk in realtà si risolve anche il problema relativo al nome del file, usando i barbatrucchi di bash.
Detto questo, mi spiego meglio, perché in effetti in alcuni punti su cui poni l'attenzione avrei potuto/dovuto essere più chiaro.
Per non confondere le cose, cerchiamo prima di risolvere la parte relativa all'elaborazione delle colonne del file di input :)
Nella spiegazione (lo scrivo a posteriori, dopo aver scritto tutto) sarò un po' prolisso... quindi ho evidenziato in nero le frasi "salienti".
A fine messaggio, c'è il punto riassuntivo che può essere letto anche saltando tutta la parte precedente :)

Elaborazione del file
Un file csv. Se vuoi semplificarti la vita rivolgiti al modulo csv di Python.
L'acquisizione delle righe del file non è un problema e per quanto segue possiamo ignorarla o darla per risolta.
Lo ho già del tutto risolta, infatti, usando le funzioni appositamente pensate nel modulo numpy, anche perché i miei file contengono valori numerici.
Pertanto possiamo anche ridurre il problema alla elaborazione degli elementi di una singola lista di Python, invece che pensare alle righe del file.
Quindi, da ora in poi, pensiamo di avere a che fare con l'elaborazione di una singola lista di numeri e che ogni elemento della lista corrisponda ad uno dei campi del file di input.
Forse volevi dire "e produrre un file che abbia come i-esima colonna il risultato dell'elaborazione della colonna originale tramite una funzione nota solo al momento in cui lancio il programma.".
Sì, mi sono espresso male.
Intendevo dire che a partire dagli elementi della lista iniziale di dimensione N (che per quanto detto precedentemente contiene gli N campi della riga letta), io devo produrre un'altra lista di dimensione M, i cui elementi sono il risultato dell'elaborazione degli N elementi di partenza.
Pertanto, parto con una lista di N elementi/campi e devo ottenere una lista con M elementi, in cui M ed N non sono uguali a priori e i singoli elementi della lista finale sono il prodotto di una generica elaborazione di tutti gli elementi della lista di partenza (all'atto pratico non sarà così, in quanto elaborerò solo una parte degli elementi iniziali, ma per non perdere generalità devo impostare la cosa in questo modo).

Print, o write? Vuoi stampare, o scrivere su un file?
Non fa molta differenza, almeno credo.
Nel senso che print (di Python 3.x) permette la stampa sia su std output, sia su file.
Tra i due, opterei per la funzione print, perché mi sembra più versatile per il mio caso.

E ora spiego meglio che intendo e come avevo pensato io la soluzione.
Come spiegato, la lista di dimensione M è quella che poi devo andare a stampare sul file di output.
Posso pertanto pensare di "produrla" e poi passarla a print come primo parametro, fargliela "spacchettare" e stamparla con un separatore e un fine riga appropriati, su standard output o su file, con una chiamata di questo tipo
(molto semplificata)

Codice: Seleziona tutto

>>> from __future__ import print_function
>>> foo = [0,1,2,3,4,5]
>>> print(*foo)
0 1 2 3 4 5
>>> print(*foo, sep = '-')
0-1-2-3-4-5
>>> print(*foo, sep = '\t')
0	1	2	3	4	5
Il problema si riduce pertanto a come far capire al programma quali elementi della lista iniziale debba elaborare e in che modo debba elaborarli.
Per semplificare ancora di più, facciamo "finta" che la lista finale abbia un solo elemento, e quindi M = 1.
Una volta risolto questo problema, infatti, si tratta solo di generalizzare il tutto, istruendo il programma


Punto riassuntivo
Visto quanto argomentato precedentemente, il problema si riduce a come introdurre nel seguente codice la possibilità di passare tramite argparse una funzione che indichi l'elaborazione degli elementi della lista (che qui ho passato come parametro, ma che in "futuro" sarà acquisita dalla lettura delle righe del file).

Codice: Seleziona tutto

#! /usr/bin/env python
# -*- coding: utf-8 -*-

from __future__ import print_function
import argparse

parser = argparse.ArgumentParser()
parser.add_argument("--lista", nargs='+', type=float, default=[1.,2.,3.,4.])
parser.add_argument("--funzione")

args = parser.parse_args()
Devo quindi far capire al programma che tipo di elaborazione della lista voglio fare... per esempio dicendogli, calcolami il seno del primo elemento più il logaritmo al quadrato del terzo elemento...
Ma la cosa deve essere generica al massimo.
Con lo stesso programma devo poter indicare il calcolo di qualsiasi combinazione matematica di tutte (o parte) le componenti della lista.

Spero di aver fatto un po' più di chiarezza :ciao:
Pirates arrrrrrrrrrr awesome!!!
«I fear not the man who has practiced 10000 kicks once,
but I fear the man who has practiced one kick 10000 times.»
Avatar utente
crap0101
Rampante Reduce
Rampante Reduce
Messaggi: 8242
Iscrizione: martedì 30 ottobre 2007, 6:33
Desktop: LXDE
Distribuzione: Ubuntu 18.04.1 LTS
Sesso: Maschile
Località: TO
Contatti:

Re: [Python] Manipolare colonne e nome di un file.dat

Messaggio da crap0101 »

in pratica hai bisogno di una o più factory che, in base a certi parametri ti costruiscono e restituiscono un qualche oggetto callable a cui passare i dati per l'elaborazione vera... per fare si fà, non so quanto possa essere generico (nel senso di trovare un trade-off tra genericità e complessità di scrittura e uso); comunque, hai presente no?
http://www.gnu.org/ http://boinc.berkeley.edu/ http://www.python-it.org/
- Ricorda le ultime parole di suo padre: «Sta' alla larga dalle chiese, figlio. La sola cosa per cui hanno la chiave è il merdaio. E giurami che non porterai mai un distintivo della legge» - W.S. Burroughs
Avatar utente
vaeVictis
Imperturbabile Insigne
Imperturbabile Insigne
Messaggi: 4703
Iscrizione: venerdì 27 luglio 2012, 17:58
Desktop: Gnome
Distribuzione: Ubuntu 20.04 64bit

Re: [Python] Manipolare colonne e nome di un file.dat

Messaggio da vaeVictis »

Grazie per l'interessamento crap0101 :)
Allora... cosa è una factory? Come ti avevo accennato in un'altra discussione (morta sul nascere :) ) sto studiando i vari design pattern per la creazione di oggetti... ma non sto capendo a cosa ti riferisci.

Sempre premettendo che il problema l'ho risolto con awk e che ora questo programma è solo uno "sfizio", in pratica mi serve di capire come poter passare (in stile awk) una funzione al programma e fare in modo che il programma la "esegua".
Intendo dire che io riesca a passare una funzione che indichi al programma come deve elaborare una lista di numeri float.
Io semplicemente scrivo una cosa del tipo:

Codice: Seleziona tutto

(log($1))^2 - sin($2)
e il programma capisce che, su una data lista, lui deve fare il la differenza tra il quadrato del logaritmo del primo campo e il seno del secondo campo.
E, ovviamente, deve poter capire le "altre possibili combinazioni" :)
Pirates arrrrrrrrrrr awesome!!!
«I fear not the man who has practiced 10000 kicks once,
but I fear the man who has practiced one kick 10000 times.»
Avatar utente
Claudio_F
Entusiasta Emergente
Entusiasta Emergente
Messaggi: 1463
Iscrizione: lunedì 28 maggio 2012, 18:49
Desktop: Mate/Gnome
Distribuzione: Ubu22.04

Re: [Python] Manipolare colonne e nome di un file.dat

Messaggio da Claudio_F »

Forse non ho capito il problema, o forse ha una soluzione banale, questo ha senso?

Codice: Seleziona tutto

from math import log, sin
#------------------------------------------------------------------------------
def elabora(*args):
    return args[0]( *(args[1:]) )
#------------------------------------------------------------------------------
argomenti = lambda p1, p2: log(p1)**2 - sin(p2),  50.6,  3.141
print(elabora(*argomenti))
Ho scritto una lambda per concisione, ma ovviamente il primo elemento della tupla 'argomenti' può essere il nome di qualsiasi altra funzione.
:ciao:
Avatar utente
vaeVictis
Imperturbabile Insigne
Imperturbabile Insigne
Messaggi: 4703
Iscrizione: venerdì 27 luglio 2012, 17:58
Desktop: Gnome
Distribuzione: Ubuntu 20.04 64bit

Re: [Python] Manipolare colonne e nome di un file.dat

Messaggio da vaeVictis »

Non ho avuto modo di rispondere prima :)
Dunque, sì, Claudio_F, il problema è abbastanza vicino a come lo hai compreso e quanto hai gentilmente postato ha senso :)

Il punti da risolvere per poter adattare il tuo esempio al mio problema sono (per come la vedo io ora) due:
1) gli elementi, che poi saranno oggetto dell'elaborazione specificata dalla funzione, devo prenderli da "dentro" una lista, magari indicandoli con il loro indice;
2) devo inoltre poter passare una generica funzione da riga di comando, magari come parametro letto dal modulo argparse.
In questa funzione devo poter indicare quali siano i singoli elementi della lista da elaborare. Per esempio devo poter scrivere log($2) - sin($5), indicando che voglio il logaritmo del secondo elemento della lista meno il seno del quinto elemento della lista. Ma devo poter anche indicare un'altra funzione di altri parametri... per esempio ($8)^2 - arctan($1) + exp($3) se voglio il quadrato dell'ottavo elemento della lista - l'arcotangente del primo elemento + l'esponenziale del terzo elemento... e così via.
E questa funzione la dovrei poter passare da riga di comando :)

Ti cito la parte di un messaggio precedente in cui c'è anche una bozza di codice:
vaeVictis [url=http://forum.ubuntu-it.org/viewtopic.php?p=4565508#p4565508][img]http://forum.ubuntu-it.org/images/icons/icona-cita.gif[/img][/url] ha scritto: [...]
Punto riassuntivo
Visto quanto argomentato precedentemente, il problema si riduce a come introdurre nel seguente codice la possibilità di passare tramite argparse una funzione che indichi l'elaborazione degli elementi della lista (che qui ho passato come parametro, ma che in "futuro" sarà acquisita dalla lettura delle righe del file).1

Codice: Seleziona tutto

#! /usr/bin/env python
# -*- coding: utf-8 -*-

from __future__ import print_function
import argparse

parser = argparse.ArgumentParser()
parser.add_argument("--lista", nargs='+', type=float, default=[1.,2.,3.,4.])
parser.add_argument("--funzione")

args = parser.parse_args()
Devo quindi far capire al programma che tipo di elaborazione della lista voglio fare... per esempio dicendogli, calcolami il seno del primo elemento più il logaritmo al quadrato del terzo elemento...
Ma la cosa deve essere generica al massimo.
Con lo stesso programma devo poter indicare il calcolo di qualsiasi combinazione matematica di tutte (o parte) le componenti della lista.

Spero di aver fatto un po' più di chiarezza :ciao:


Sinceramente io non saprei proprio come fare... e sto sommerso da talmente tanta roba da fare che non riesco neanche tanto a concentrarmi sul problema.

Se non sono stato abbastanza chiaro, chiedi pure.
E grazie ancora per l'interessamento.
:ciao:
Pirates arrrrrrrrrrr awesome!!!
«I fear not the man who has practiced 10000 kicks once,
but I fear the man who has practiced one kick 10000 times.»
Avatar utente
crap0101
Rampante Reduce
Rampante Reduce
Messaggi: 8242
Iscrizione: martedì 30 ottobre 2007, 6:33
Desktop: LXDE
Distribuzione: Ubuntu 18.04.1 LTS
Sesso: Maschile
Località: TO
Contatti:

Re: [Python] Manipolare colonne e nome di un file.dat

Messaggio da crap0101 »

io non sono sicuro di aver capito bene, puoi fare un esempio con una linea di comando per awk (che scrivevi aver risolto con quello)?

btw, se ho inteso bene, per "dire al programma" quali funzioni utilizzare e come nello stile dell'esempio di awk

Codice: Seleziona tutto

(log($1))^2 - sin($2)
puoi fare la stessa cosa anche con python (il codice immagino sia un argomento passato al programma) e poi ci vai brutalmente di eval e/o compile etc, altrimenti devi costruire un miniparser per parsare quelle espressioni.
http://www.gnu.org/ http://boinc.berkeley.edu/ http://www.python-it.org/
- Ricorda le ultime parole di suo padre: «Sta' alla larga dalle chiese, figlio. La sola cosa per cui hanno la chiave è il merdaio. E giurami che non porterai mai un distintivo della legge» - W.S. Burroughs
Scrivi risposta

Ritorna a “Programmazione”

Chi c’è in linea

Visualizzano questa sezione: 0 utenti iscritti e 2 ospiti