2017-08-06 3 views
-1

Je travaille avec un fichier csv en Python en utilisant Pandas. J'ai quelques difficultés à penser comment atteindre l'objectif suivant. Ce que je dois réaliser est de regrouper les entrées en utilisant une fonction de similarité. Par exemple, chaque groupe X doit contenir toutes les entrées où chaque couple du groupe diffère d'au plus Y sur une certaine valeur de colonne d'attribut.(Python) Pandas - GroupBy() utilisant une fonction de similarité

Étant donné cet exemple de CSV:

<pre> 
 
name;sex;city;age 
 
john;male;newyork;20 
 
jack;male;newyork;21 
 
mary;female;losangeles;45 
 
maryanne;female;losangeles;48 
 
eric;male;san francisco;29 
 
jenny;female;boston2;30 
 
mattia;na;BostonDynamics;50 
 
</pre>

et compte tenu de la colonne d'âge, avec une différence d'au plus 3 sur cette valeur que je recevrais les groupes suivants:

A = {john;male;newyork;20 
    jack;male;newyork;21} 
B={eric;male;san francisco;29 
    jenny;female;boston2;30} 
C={mary;female;losangeles;45 
    maryanne;female;losangeles;48} 
D={maryanne;female;losangeles;48 
    mattia;na;BostonDynamics;50} 

En fait, c'est mon travail, mais j'espère qu'il existe quelque chose de plus pythonique.

import pandas as pandas 
import numpy as numpy 

def main(): 
    csv_path = "../resources/dataset_string.csv" 
    csv_data_frame = pandas.read_csv(csv_path, delimiter=";") 
    print("\nOriginal Values:") 
    print(csv_data_frame) 

    sorted_df = csv_data_frame.sort_values(by=["age", "name"], kind="mergesort") 
    print("\nSorted Values by AGE & NAME:") 
    print(sorted_df) 

    min_age = int(numpy.min(sorted_df["age"])) 
    print("\nMin_Age:", min_age) 
    max_age = int(numpy.max(sorted_df["age"])) 
    print("\nMax_Age:", max_age) 

    threshold = 3 
    bins = numpy.arange(min_age, max_age, threshold) 
    print("Bins:", bins) 
    ind = numpy.digitize(sorted_df["age"], bins) 
    print(ind) 

    print("\n\nClustering by hand:\n") 
    current_min = min_age 
    for cluster in range(min_age, max_age, threshold): 
     next_min = current_min + threshold 
     print("<Cluster({})>".format(cluster)) 
     print(sorted_df[(current_min <= sorted_df["age"]) & (sorted_df["age"] <= next_min)]) 
     print("</Cluster({})>\n".format(cluster + threshold)) 
     current_min = next_min 


if __name__ == "__main__": 
    main() 
+0

Je suis sûr que vous ne pouvez pas faire cela chez les pandas. Pourquoi n'utilisez-vous pas simplement un algorithme de clustering de sklearn, par ex. k-signifie? Une fois que vous avez l'indice de clustering calculé par sklearn, vous pouvez facilement le grouper. –

+0

J'ai lu que j'avais besoin de connaître le nombre de clusters et je ne pouvais pas trouver de moyen de le calculer car les données ne pouvaient être distribuées aléatoirement que dans un pourcentage de clusters. Si elles étaient réparties équitablement (au moins une fois par grappe), j'obtiendrais les grappes math.ceil ((max - min)/threshold). Est-il possible d'insérer correctement les données dans le cluster correspondant avec k-means? Un petit exemple serait très utile. Je vais chercher à ce sujet. Merci beaucoup. –

Répondre

1

Sur un attribut est simple:

  1. Trier
  2. scan les données Linéairement, et chaque fois que le seuil est violé, commencer un nouveau groupe.

Bien que ce ne soit pas optimal, il devrait être meilleur que ce que vous avez déjà, à moindre coût. Cependant, dans le cas multivarié, trouver les groupes optimaux est supposé NP-difficile, donc la recherche du groupement optimal nécessitera une recherche en force brute en temps exponentiel. Vous aurez donc besoin d'approximer ceci, soit par AGNES (en O (n³)) ou par CLINK (qualité généralement inférieure, mais O (n²)).

Comme cela est assez coûteux, ce ne sera pas un simple opérateur de votre trame de données.