Diviser une grande trame de données pandas


86

J'ai une grande trame de données avec 423244 lignes. Je veux diviser ceci en 4. J'ai essayé le code suivant qui a donné une erreur?ValueError: array split does not result in an equal division

for item in np.split(df, 4):
    print item

Comment diviser ce dataframe en 4 groupes?


Nous voulons une np.split(df, N)fonction s'il vous plaît.
Sören

Réponses:


182

Utilisez np.array_split:

Docstring:
Split an array into multiple sub-arrays.

Please refer to the ``split`` documentation.  The only difference
between these functions is that ``array_split`` allows
`indices_or_sections` to be an integer that does *not* equally
divide the axis.

In [1]: import pandas as pd

In [2]: df = pd.DataFrame({'A' : ['foo', 'bar', 'foo', 'bar',
   ...:                           'foo', 'bar', 'foo', 'foo'],
   ...:                    'B' : ['one', 'one', 'two', 'three',
   ...:                           'two', 'two', 'one', 'three'],
   ...:                    'C' : randn(8), 'D' : randn(8)})

In [3]: print df
     A      B         C         D
0  foo    one -0.174067 -0.608579
1  bar    one -0.860386 -1.210518
2  foo    two  0.614102  1.689837
3  bar  three -0.284792 -1.071160
4  foo    two  0.843610  0.803712
5  bar    two -1.514722  0.870861
6  foo    one  0.131529 -0.968151
7  foo  three -1.002946 -0.257468

In [4]: import numpy as np
In [5]: np.array_split(df, 3)
Out[5]: 
[     A    B         C         D
0  foo  one -0.174067 -0.608579
1  bar  one -0.860386 -1.210518
2  foo  two  0.614102  1.689837,
      A      B         C         D
3  bar  three -0.284792 -1.071160
4  foo    two  0.843610  0.803712
5  bar    two -1.514722  0.870861,
      A      B         C         D
6  foo    one  0.131529 -0.968151
7  foo  three -1.002946 -0.257468]

Merci beaucoup! En plus de cela, je veux appliquer une fonction à chaque groupe Comment accéder aux groupes un par un?
Nilani Algiriyage

7
@NilaniAlgiriyage - array_splitrenvoie une liste de DataFrames, donc vous pouvez simplement parcourir la liste ...
racine le

Je divise le dataframe car il est trop grand. Je veux prendre le premier groupe et appliquer la fonction, puis le second groupe et appliquer la fonction etc. alors comment accéder à chaque groupe?
Nilani Algiriyage

1
Comment ne pas obtenir une AttributeError car Dataframe n'a pas de «taille».
Boosted_d16

2
Cette réponse est obsolète:AttributeError: 'DataFrame' object has no attribute 'size'
Tjorriemorrie

33

Je voulais faire de même, et j'ai eu d'abord des problèmes avec la fonction split, puis des problèmes avec l'installation de pandas 0.15.2, donc je suis retourné à mon ancienne version, et j'ai écrit une petite fonction qui fonctionne très bien. J'espère que cela peut vous aider!

# input - df: a Dataframe, chunkSize: the chunk size
# output - a list of DataFrame
# purpose - splits the DataFrame into smaller chunks
def split_dataframe(df, chunk_size = 10000): 
    chunks = list()
    num_chunks = len(df) // chunk_size + 1
    for i in range(num_chunks):
        chunks.append(df[i*chunk_size:(i+1)*chunk_size])
    return chunks

5
beaucoup plus rapide que d'utiliser np.array_split ()
jgaw

4
La bonne façon de calculer numberChunks import math numberChunks = math.ceil (len (df) / chunkSize)
Sergey Leyko

21

Je suppose que maintenant nous pouvons utiliser plain ilocavec rangepour cela.

chunk_size = int(df.shape[0] / 4)
for start in range(0, df.shape[0], chunk_size):
    df_subset = df.iloc[start:start + chunk_size]
    process_data(df_subset)
    ....

1
Simple et intuitif
rmstmppr

13

Sachez que np.array_split(df, 3)le dataframe divise en 3 sous-dataframes, tandis que la split_dataframefonction définie dans la réponse de @ elixir , lorsqu'elle est appelée en tant que split_dataframe(df, chunk_size=3), divise le dataframe toutes les chunk_sizelignes.

Exemple:

Avec np.array_split:

df = pd.DataFrame([1,2,3,4,5,6,7,8,9,10,11], columns=['TEST'])
df_split = np.array_split(df, 3)

... vous obtenez 3 sous-dataframes:

df_split[0] # 1, 2, 3, 4
df_split[1] # 5, 6, 7, 8
df_split[2] # 9, 10, 11

Avec split_dataframe:

df_split2 = split_dataframe(df, chunk_size=3)

... vous obtenez 4 sous-dataframes:

df_split2[0] # 1, 2, 3
df_split2[1] # 4, 5, 6
df_split2[2] # 7, 8, 9
df_split2[3] # 10, 11

J'espère que j'ai raison, et que cela est utile.


existe-t-il un moyen simple de rendre ce processus aléatoire. Je ne peux que penser à ajouter une colonne rondom, à diviser et à supprimer la colonne aléatoire, mais il pourrait y avoir un moyen plus simple
Rutger Hofste

doivent-ils être de taille égale?
InquilineKea

8

Mise en garde:

np.array_splitne fonctionne pas avec numpy-1.9.0. J'ai vérifié: cela fonctionne avec la version 1.8.1.

Erreur:

Dataframe n'a pas d'attribut 'size'


6
J'ai déposé un bogue dans le github pandas: github.com/pydata/pandas/issues/8846 semble qu'il est déjà corrigé pour les pandas 0.15.2
yemu

4

Vous pouvez utiliser groupby, en supposant que vous ayez un index énuméré par nombre entier:

import math
df = pd.DataFrame(dict(sample=np.arange(99)))
rows_per_subframe = math.ceil(len(df) / 4.)

subframes = [i[1] for i in df.groupby(np.arange(len(df))//rows_per_subframe)]

Remarque: groupbyrenvoie un tuple dans lequel le 2ème élément est le dataframe, donc l'extraction légèrement compliquée.

>>> len(subframes), [len(i) for i in subframes]
(4, [25, 25, 25, 24])

1

J'ai également constaté que np.array_split ne fonctionnait pas avec Pandas DataFrame, ma solution consistait à diviser uniquement l'index du DataFrame, puis à introduire une nouvelle colonne avec l'étiquette "groupe":

indexes = np.array_split(df.index,N, axis=0)
for i,index in enumerate(indexes):
   df.loc[index,'group'] = i

Cela rend les opérations groupées très pratiques, par exemple le calcul de la valeur moyenne de chaque groupe:

df.groupby(by='group').mean()

0

vous pouvez utiliser la compréhension de liste pour le faire en une seule ligne

n = 4
chunks = [df[i:i+n] for i in range(0,df.shape[0],n)]
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.