Cet article est l'article du 19e jour du Calendrier de l'Avent Python Partie 2 2015.
J'ai essayé de m'inscrire au Calendrier de l'Avent, mais récemment je n'ai pas écrit un tel Python et même si je l'écris, je ne peux pas l'écrire parce que j'ai fait trop de choses spéciales dans les affaires, donc ça me rappelle un peu maintenant, mais c'est une petite histoire de pandas. J'écrirai sur les pandas, qui sont familiers dans le prétraitement et l'agrégation des données, et sur Multiindex, que je connais mais est un peu difficile à comprendre.
Le code qui apparaît ci-dessous est
import pandas as pd
Il est écrit sur le principe que c'est fait. De plus, la table collée est une copie de la version to_html
, elle est donc légèrement différente de l'affichage sur le notebook jupyter.
MultiIndex / Advanced Indexing Une fonction pour indexer plusieurs colonnes avec DataFrame de pandas. Ceci est utile lorsque plusieurs valeurs sont utilisées comme clés pour identifier de manière unique les données.
Les index ordinaires sont appelés dans cet article Index unique pour plus de commodité, contrairement à Multi Index. (Il n'y a pas de tel type)
Préparez le csv suivant pour l'explication
sample.csv
name,year,product,expected,actual
Taro,2013,A,116,119
Taro,2013,B,131,149
Taro,2014,A,151,124
Taro,2014,B,125,107
Taro,2015,A,135,109
Taro,2015,B,142,148
Hanako,2013,A,170,130
Hanako,2013,B,113,190
Hanako,2014,A,102,142
Hanako,2014,B,183,125
Hanako,2015,A,169,120
Hanako,2015,B,134,199
Lisez ceci avec les pandas.
df1 = pd.read_csv('sample.csv')
name | year | product | expected | actual | |
---|---|---|---|---|---|
0 | Taro | 2013 | A | 116 | 119 |
1 | Taro | 2013 | B | 131 | 149 |
2 | Taro | 2014 | A | 151 | 124 |
3 | Taro | 2014 | B | 125 | 107 |
4 | Taro | 2015 | A | 135 | 109 |
5 | Taro | 2015 | B | 142 | 148 |
6 | Hanako | 2013 | A | 170 | 130 |
7 | Hanako | 2013 | B | 113 | 190 |
8 | Hanako | 2014 | A | 102 | 142 |
9 | Hanako | 2014 | B | 183 | 125 |
10 | Hanako | 2015 | A | 169 | 120 |
11 | Hanako | 2015 | B | 134 | 199 |
Les étiquettes de ligne de cette table, «0,1,2 ...», sont «data.index», et les étiquettes de colonne »,« nom »,« année », ...« sont »des colonnes de données». A également un type de données de pandas.Index
.
Parce que pandas.Index
a un membre appelé nom
df1.index.name = "id"
df1.columns.name = "header"
Puis
header | name | year | product | expected | actual |
---|---|---|---|---|---|
id | |||||
0 | Taro | 2013 | A | 116 | 119 |
1 | Taro | 2013 | B | 131 | 149 |
2 | Taro | 2014 | A | 151 | 124 |
3 | Taro | 2014 | B | 125 | 107 |
4 | Taro | 2015 | A | 135 | 109 |
5 | Taro | 2015 | B | 142 | 148 |
6 | Hanako | 2013 | A | 170 | 130 |
7 | Hanako | 2013 | B | 113 | 190 |
8 | Hanako | 2014 | A | 102 | 142 |
9 | Hanako | 2014 | B | 183 | 125 |
10 | Hanako | 2015 | A | 169 | 120 |
11 | Hanako | 2015 | B | 134 | 199 |
df1["name"]
production
id
0 Taro
1 Taro
2 Taro
3 Taro
4 Taro
5 Taro
6 Hanako
7 Hanako
8 Hanako
9 Hanako
10 Hanako
11 Hanako
Name: name, dtype: object
df1.loc[3]
production
header
name Taro
year 2014
product B
expected 125
actual 107
Name: 3, dtype: object
df1.iloc[3]
Cet index de temps est un index de ligne, donc la sortie est la même.
df1.ix[3:5,"product":"actual"]
production
product | expected | actual | |
---|---|---|---|
3 | B | 125 | 107 |
4 | A | 135 | 109 |
5 | B | 142 | 148 |
df1[(df1["name"] == "Hanako")&(df1["product"] == "A")]
production
header | name | year | product | expected | actual |
---|---|---|---|---|---|
id | |||||
6 | Hanako | 2013 | A | 170 | 130 |
8 | Hanako | 2014 | A | 102 | 142 |
10 | Hanako | 2015 | A | 169 | 120 |
Voir d'autres articles et livres pour plus de détails.
Le sujet principal est d'ici. Comme vous pouvez le voir, les données que vous venez de lire
Dans un tel cas, utilisez MultiIndex pour organiser proprement les données.
df2 = pd.read_csv("sample.csv",index_col=["name","year","product"])
expected | actual | |||
---|---|---|---|---|
name | year | product | ||
Taro | 2013 | A | 116 | 119 |
B | 131 | 149 | ||
2014 | A | 151 | 124 | |
B | 125 | 107 | ||
2015 | A | 135 | 109 | |
B | 142 | 148 | ||
Hanako | 2013 | A | 170 | 130 |
B | 113 | 190 | ||
2014 | A | 102 | 142 | |
B | 183 | 125 | ||
2015 | A | 169 | 120 | |
B | 134 | 199 |
Après lecture des données ou lors de l'application de MultiIndex au DataFrame créé par divers traitements
PostScript 2016/3/18 </ font>
Si vous utilisez la fonction set_index
, la colonne spécifiée sera indexée. (Je ne le savais pas car il n'était pas répertorié sur la page MultiIndex du document officiel ...)
df2 = df1.set_index(["name","year","product"], drop=True)
Si drop = True
, la colonne indexée sera supprimée.
Au retour
df1 = df2.reset_index()
À Fin de l'ajout </ font>
pd.MultiIndex.from_arrays()
pd.MultiIndex.from_product()
pd.MultiIndex.from_tuples()
Si vous utilisez autour, ce sera gérable. Au fait, pd.MultiIndex.from_product
crée un index pour les boucles imbriquées lors du passage de plusieurs collections (comme itertools.product). Par exemple, pour créer le même index que «df2»
pd.MultiIndex.from_product((["Taro","Hanako"],[2013,2014,2015],["A","B"]),\
names=["name","year","product"])
Tu peux le faire.
Lors de la sélection d'une ligne, passez la touche d'index.
df2.loc[("Taro",2013,"A")]
production
expected 116
actual 119
Name: (Taro, 2013, A), dtype: int64
Si vous passez un taple à mi-chemin, le tableau sera retourné, mais comme PerformanceWarning sera émis pour la spécification jusqu'au niveau à mi-chemin, il est préférable de ne pas l'utiliser sauf lorsque vous souhaitez regarder temporairement à l'intérieur. Il n'y a aucun problème si vous spécifiez le premier niveau (nom dans ce cas) ou tous les niveaux.
df2.loc[("Taro",2013)]
Sortie (PerformanceWarning)
expected | actual | |
---|---|---|
product | ||
A | 116 | 119 |
B | 131 | 149 |
Utilisez xs
pour spécifier jusqu'au niveau intermédiaire ou uniquement au milieu
df2.xs(["Taro","A"],level=[0,2])
production
expected | actual | |
---|---|---|
year | ||
2013 | 116 | 119 |
2014 | 151 | 124 |
2015 | 135 | 109 |
L'avertissement n'est plus affiché, mais même si vous écrivez le même processus que ci-dessus, celui-ci est un peu plus lent ...
Puisque pandas.Index n'est pas pandas.Series, il ne peut pas être utilisé comme une ligne normale, et il est sobre et stressant. Ensuite, je voudrais dire qu'il n'y a pas de mal à conserver Single Index et Series, mais comme il y a beaucoup d'efforts, réfléchissez à où les utiliser.
Comme je l'ai écrit plus tôt, c'est probablement l'utilisation principale.
df2.loc[("Taro",2013,"A")]
Si vous essayez de faire de même avec Single Index,
df1[(df1["name"] == "Taro")&(df1["year"] == 2013)&(df1["product"] == "A")].iloc[0]
On a l'impression que c'est sale (il y a peut-être une meilleure façon de l'écrire).
Bien sûr, il y a aussi une différence de vitesse. Lorsque j'ai essayé d'utiliser environ 50000 données, j'ai constaté qu'il n'y avait qu'une différence de 2 à 3 fois dans un essai. J'ai essayé de vérifier avec %% timeit
, mais `` df2` semble être mis en cache et je n'ai pas pu comparer.
De plus, si vous n'êtes pas sûr qu'il existe des données correspondant à la clé spécifiée, MultiIndex
("Taro",2013,"A") in df2.index
Mais avec un seul index
df1[(df1["name"] == "Taro")&(df1["year"] == 2013)&(df1["product"] == "A")].shape[0]>0
Je dois le faire (il y a peut-être une meilleure façon de l'écrire)
Étant donné que la sortie de MultiIndex avec des index de clés imbriqués est très visible pour les humains, il est possible d'utiliser MultiIndex uniquement pour la sortie.
DataFrame peut produire dans de nombreux formats tels que html, excel, latex, etc., et même s'il s'agit d'Excel, il combinera correctement les cellules selon MultiIndex, donc c'est pratique.
Au fait, avec df.to_csv
, même si c'est MultiIndex, il affichera toutes les lignes correctement.
Recommended Posts