J'ai un fichier txt comprenant 9 colonnes et 6 lignes. Les 8 premières colonnes sont l'une de ces valeurs: "1", "2" et "3". J'ai nommé ces colonnes de "A" à "H". J'ai nommé la dernière colonne: "classe". La dernière colonne est un nom: "HIGH". Voici le fichier txt (data.txt):

1,1,1,1,2,1,1,3,HIGH 
1,1,1,2,2,1,1,3,HIGH 
1,1,1,1,1,1,1,3,HIGH 
1,1,1,2,1,1,1,3,HIGH 
1,1,1,3,2,1,1,3,HIGH 
1,1,1,2,1,2,1,3,HIGH

J'essaie de compter le nombre de chaque valeur dans chaque colonne et d'imprimer une liste qui devrait avoir 3 composants, y compris les nombres de valeurs «1», «2» et «3» dans cette colonne respectivement . Par exemple, dans la première colonne (par exemple A), toutes les valeurs sont "1". J'espère obtenir: A: [6,0,0] . Pour la 8ème colonne (par exemple H) où toutes les valeurs sont "3", j'espère obtenir: H: [0,0,6] ou pour la quatrième colonne (par exemple D) j'en ai deux " 1 ", trois" 2 "et un" 3 ". J'attends donc: D: [2,3,1] . J'ai essayé de le faire en utilisant pandas et collection . Voici ce que j'ai fait:

import pandas as pd
from collections import Counter

df = pd.read_csv('data.txt')
df.columns = ['A','B','C','D','E','F','G','H','class']

X = df.ix[:, 0:8].values
y = df.ix[:, 8].values

deg = ['HIGH']

names = ['A','B','C','D','E','F','G','H']

for j in range(0, 8):

    freqs = Counter(X[y == deg[0], j])
    print(names[j],':',list(freqs.values()))

La sortie du code ci-dessus sont des listes vides. Voici ce qu'il renvoie:

A : []
B : []
C : []
D : []
E : []
F : []
G : []
H : []

Comment puis-je modifier le code ci-dessus pour obtenir ce que je veux? Merci!

3
Leo 27 août 2020 à 07:55

4 réponses

Meilleure réponse

Définissez la fonction suivante:

def cntInts(col):
    vc = col.value_counts()
    return [ vc.get(i, 0) for i in range(1,4) ]

Ensuite, appliquez-le et imprimez les résultats:

for k, v in df.loc[:, 'A':'H'].apply(cntInts).iteritems():
    print(f'{k}: {v}')

Pour votre échantillon de données, j'ai obtenu:

A: [6, 0, 0]
B: [6, 0, 0]
C: [6, 0, 0]
D: [2, 3, 1]
E: [3, 3, 0]
F: [5, 1, 0]
G: [6, 0, 0]
H: [0, 0, 6]

Ou peut-être suffit-il d'appeler simplement:

df.loc[:, 'A':'H'].apply(cntInts)

Cette fois, le résultat est une Série , qui, une fois imprimée, donne:

A    [6, 0, 0]
B    [6, 0, 0]
C    [6, 0, 0]
D    [2, 3, 1]
E    [3, 3, 0]
F    [5, 1, 0]
G    [6, 0, 0]
H    [0, 0, 6]
dtype: object

Éditer

Suite à vos commentaires, je suppose qu'il y a un problème avec vos données.

Pour retracer la raison réelle:

  1. Définissez une variable chaîne:

     txt = '''1,1,1,1,2,1,1,3,HIGH 
     1,1,1,2,2,1,1,3,HIGH 
     1,1,1,1,1,1,1,3,HIGH 
     1,1,1,2,1,1,1,3,HIGH 
     1,1,1,3,2,1,1,3,HIGH 
     1,1,1,2,1,2,1,3,HIGH'''
    
  2. Courir:

     import io
     df = pd.read_csv(io.StringIO(txt), names=['A','B','C','D','E','F','G','H','class'])
    
  3. Exécutez mon code sur mes données. Le résultat devrait être exactement comme prévu.

  4. Ensuite, lisez votre fichier d'entrée (également dans df ) et réexécutez mon code. Il y a probablement une différence entre vos données et les miennes. Recherchez en particulier les espaces supplémentaires dans votre fichier d'entrée, vérifiez également les types de colonnes (après read_csv ).

1
Valdi_Bo 27 août 2020 à 18:34

Travailler dans python, puisque votre résultat final est un dictionnaire:

from string import ascii_uppercase
from collections import Counter, defaultdict
from itertools import chain, product
import csv    

d = defaultdict(list)
fieldnames = ascii_uppercase[:9]
# test.csv is your file above
with open('test.csv') as csvfile:    
    reader = csv.DictReader(csvfile, fieldnames = list(fieldnames))
    reader = Counter(chain.from_iterable(row.items() for row in reader))
    for col, value in product(fieldnames, ("1","2","3")):
        if col != fieldnames[-1]:
            d[col].append(reader.get((col,value), 0))      

Imprimer (d)

defaultdict(list,
            {'A': [6, 0, 0],
             'B': [6, 0, 0],
             'C': [6, 0, 0],
             'D': [2, 3, 1],
             'E': [3, 3, 0],
             'F': [5, 1, 0],
             'G': [6, 0, 0],
             'H': [0, 0, 6]})
1
sammywemmy 27 août 2020 à 05:49

La solution avec les collections est de sélectionner toutes les colonnes sans dernier, de convertir Counter en Series, donc la sortie est DataFrame, remplacer les valeurs manquantes par DataFrame.fillna, convertit les valeurs en entiers et les dernières en dictionnaire par DataFrame.to_dict:

from collections import Counter

d = (df.iloc[:, :-1].apply(lambda x: pd.Series(Counter(x)))
       .fillna(0)
       .astype(int)
       .to_dict("list"))
print (d)
{'A': [6, 0, 0], 'B': [6, 0, 0], 
 'C': [6, 0, 0], 'D': [1, 4, 1], 
 'E': [3, 3, 0], 'F': [5, 1, 0], 
 'G': [6, 0, 0], 'H': [0, 0, 6]}

Seule solution pandas avec pandas.value_counts:

d = (df.iloc[:, :-1].apply(pd.value_counts)
       .fillna(0)
       .astype(int)
       .to_dict("list"))
print (d)
{'A': [6, 0, 0], 'B': [6, 0, 0],
 'C': [6, 0, 0], 'D': [2, 3, 1], 
 'E': [3, 3, 0], 'F': [5, 1, 0], 
 'G': [6, 0, 0], 'H': [0, 0, 6]}
1
jezrael 27 août 2020 à 05:36

Utilisez pandas.Series.value_counts

df.loc[:, :"H"].apply(pd.Series.value_counts).fillna(0).to_dict("l")

Production:

{'A': [6.0, 0.0, 0.0],
 'B': [6.0, 0.0, 0.0],
 'C': [6.0, 0.0, 0.0],
 'D': [2, 3, 1],
 'E': [3.0, 3.0, 0.0],
 'F': [5.0, 1.0, 0.0],
 'G': [6.0, 0.0, 0.0],
 'H': [0.0, 0.0, 6.0]}
2
Chris 27 août 2020 à 05:05