Je génère un df à partir du résultat de la ligne de commande avec du code comme ci-dessous: -

df_output_lines = [s.split() for s in os.popen("my command linecode").read().splitlines()]
df_output_lines  = list(filter(None, df_output_lines))

Puis le convertir en un dataframe: -

df=pd.DataFrame(df_output_lines)
df

Les données sont dans le format ci-dessous: -

abc = pd.DataFrame([['time:"08:59:38.000"', 'instance:"(null)"','id:"3214039276626790405"'],['time:"08:59:38.000"', 'instance:"(Ops-MacBook-Pro.local)"','id:"3214039276626790405"'],['time:"08:59:38.000"', 'instance:"(Ops-MacBook-Pro.local)"','id:"3214039276626790405"']])
abc

enter image description here

Je veux le filtrer de manière à ce que la valeur before : soit le nom de la colonne et les valeurs dans quotes " " la valeur et il en va de même pour toutes les colonnes. La sortie doit être comme: - entrez la description de l'image ici

À partir de maintenant, je le fais à la dure: -

abc.rename(columns={0:'time',1:'instance',2:'id'},inplace=True)

Puis

abc['time'] = abc['time'].map(lambda x: str(x)[:-1])
abc['time'] = abc['time'].map(lambda x: str(x)[6:])

abc['instance'] = abc['instance'].map(lambda x: str(x)[:-1])
abc['instance'] = abc['instance'].map(lambda x: str(x)[10:])

abc['id'] = abc.id.str.extract('(\d+)', expand=True).astype(int)

Toute suggestion d'expression lambda ou toute doublure pour ce faire.

Ma sortie pour le journal brut est comme ci-dessous: -

    time:"11:22:20.000" instance:"(null)" id:"723927731576482920" channel:"sip:confctl.com" type:"control" elapsedtime:"0.000631" level:"info" operation:"Init" message:"Initialize (version 4.9.0002.30618) ... "

    time:"11:22:21.000" instance:"Ops-MacBook-Pro.local" id:"723927731576482920" channel:"sip:confctl.com" type:"control" elapsedtime:"0.067122" level:"info" operation:"Connect" message:"Connecting to https://hrpd.www.vivox.com/api2/"

    time:"11:22:23.000" instance:"Ops-MacBook-Pro.local" id:"723927731576482920" channel:"sip:confctl-.com" type:"control" elapsedtime:"2.685700" level:"info" operation:"Connect" message:"Connected to https://hrpd.www.vivox.com/api2/"

    time:"11:22:23.000" instance:"Ops-MacBook-Pro.local" id:"723927731576482920" channel:"sip:confctl-.com" type:"control" elapsedtime:"2.814268" level:"info" operation:"Login" message:"Logged in .tester_food."

    time:"11:22:23.000" instance:"Ops-MacBook-Pro.local" id:"723927731576482920" channel:"sip:confctl-.com" type:"control" elapsedtime:"2.912255" level:"error" operation:"Call" message:".tester_food. failed to join sip:confctl-2@hrpd.vivox.com error:Access token has invalid signature(403)"

 time:"12:30:41.000" instance:"Ops-MacBook-Pro.local" id:"10316899144153251411" channel:"sip:confctl-2@hrpd.vivox.com" type:"media" sampleperiod:"0.000000" incomingpktsreceived:"0" incomingpktsexpected:"0" incomingpktsloss:"0" incomingpktssoutoftime:"0" incomingpktsdiscarded:"0" outgoingpktssent:"0" predictedmos:"3" latencypktssent:"0" latencycount:"0" latencysum:"0.000000" latencymin:"0.000000" latencymax:"0.000000" callid:"2477580077" r_factor:"0.000000"
1
user10177566 19 nov. 2018 à 19:14

3 réponses

Meilleure réponse

Alimentez la liste des dictionnaires vers pd.DataFrame

Le constructeur pd.DataFrame accepte directement une liste de dictionnaires. Vous pouvez utiliser str.rstrip et str.split dans une liste de compréhension:

res = pd.DataFrame([dict(i.rstrip('"').split(':"') for i in row) for row in abc.values])

print(res)

                    id                 instance          time
0  3214039276626790405                   (null)  08:59:38.000
1  3214039276626790405  (Ops-MacBook-Pro.local)  08:59:38.000
2  3214039276626790405  (Ops-MacBook-Pro.local)  08:59:38.000

La logique que vous utilisez pour déterminer que seules les chaînes 'null' sont entourées de parenthèses n'est pas claire.

0
jpp 19 nov. 2018 à 16:22

Étant donné votre exemple d'entrée de:

time:"11:22:20.000" instance:"(null)" id:"723927731576482920" channel:"sip:confctl.com" type:"control" elapsedtime:"0.000631" level:"info" operation:"Init" message:"Initialize (version 4.9.0002.30618) ... "

time:"11:22:21.000" instance:"Ops-MacBook-Pro.local" id:"723927731576482920" channel:"sip:confctl.com" type:"control" elapsedtime:"0.067122" level:"info" operation:"Connect" message:"Connecting to https://hrpd.www.vivox.com/api2/"

time:"11:22:23.000" instance:"Ops-MacBook-Pro.local" id:"723927731576482920" channel:"sip:confctl-.com" type:"control" elapsedtime:"2.685700" level:"info" operation:"Connect" message:"Connected to https://hrpd.www.vivox.com/api2/"

time:"11:22:23.000" instance:"Ops-MacBook-Pro.local" id:"723927731576482920" channel:"sip:confctl-.com" type:"control" elapsedtime:"2.814268" level:"info" operation:"Login" message:"Logged in .tester_food."

time:"11:22:23.000" instance:"Ops-MacBook-Pro.local" id:"723927731576482920" channel:"sip:confctl-.com" type:"control" elapsedtime:"2.912255" level:"error" operation:"Call" message:".tester_food. failed to join sip:confctl-2@hrpd.vivox.com error:Access token has invalid signature(403)"

Qui vient de votre commande os.popen, puis nous filtrons les lignes vides et essayons de shlex.split la ligne afin que les espaces dans les éléments cités soient préservés (mais les guillemets eux-mêmes sont supprimés), par exemple:

import os
import shlex
import pandas as pd

rows = [shlex.split(line) for line in os.popen("my command linecode").read().splitlines() if line.strip()]

Cela vous donnera, par exemple rows[0]:

['time:11:22:20.000',
 'instance:(null)',
 'id:723927731576482920',
 'channel:sip:confctl.com',
 'type:control',
 'elapsedtime:0.000631',
 'level:info',
 'operation:Init',
 'message:Initialize (version 4.9.0002.30618) ... ']

Vous partitionnez ensuite ceux-ci sur : pour séparer l'identifiant de la valeur et l'introduisez dans un pd.DataFrame, par exemple:

df = pd.DataFrame(dict(col.partition(':')[::2] for col in row) for row in rows)

Vous donnant un df de:

            channel elapsedtime                  id               instance  level                                            message operation          time     type
0   sip:confctl.com    0.000631  723927731576482920                 (null)   info           Initialize (version 4.9.0002.30618) ...       Init  11:22:20.000  control
1   sip:confctl.com    0.067122  723927731576482920  Ops-MacBook-Pro.local   info     Connecting to https://hrpd.www.vivox.com/api2/   Connect  11:22:21.000  control
2  sip:confctl-.com    2.685700  723927731576482920  Ops-MacBook-Pro.local   info      Connected to https://hrpd.www.vivox.com/api2/   Connect  11:22:23.000  control
3  sip:confctl-.com    2.814268  723927731576482920  Ops-MacBook-Pro.local   info                            Logged in .tester_food.     Login  11:22:23.000  control
4  sip:confctl-.com    2.912255  723927731576482920  Ops-MacBook-Pro.local  error  .tester_food. failed to join sip:confctl-2@hrp...      Call  11:22:23.000  control
0
Jon Clements 19 nov. 2018 à 17:23

Bien que la réponse soit déjà produite, Cependant, nous aimerions ajouter une approche de base regex pour y parvenir:

>>> abc
                  time                            instance                        id
0  time:"08:59:38.000"                   instance:"(null)"  id:"3214039276626790405"
1  time:"08:59:38.000"  instance:"(Ops-MacBook-Pro.local)"  id:"3214039276626790405"
2  time:"08:59:38.000"  instance:"(Ops-MacBook-Pro.local)"  id:"3214039276626790405"

Il suffit d'appliquer regex=True dans DataFrame.

>>> abc.replace('instance:|id:|time:|\"|[()]', '',regex=True)
           time               instance                   id
0  08:59:38.000                   null  3214039276626790405
1  08:59:38.000  Ops-MacBook-Pro.local  3214039276626790405
2  08:59:38.000  Ops-MacBook-Pro.local  3214039276626790405

OR   

# abc.replace('(instance:|id:|time:)|\"|[()]', '',regex=True)

explication de l'expression régulière:

  • 1ère alternative 'instance:' instance: correspond à l'instance des caractères: littéralement (sensible à la casse)

  • 2e id alternatif: id: correspond aux caractères id: littéralement (sensible à la casse)

  • 3e temps alternatif: temps: correspond au temps des caractères: littéralement (sensible à la casse)

  • 4e alternative \ "correspond au caractère" littéralement (sensible à la casse)

  • 5e alternative [()] 'Correspond à un seul caractère présent dans la liste ci-dessous [()] () correspond à un seul caractère dans la liste () (sensible à la casse)

0
Karn Kumar 19 nov. 2018 à 17:31