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?

Nilani Algiriyage
la source
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]
racine
la source
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
élixir
la source
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)
    ....
pratpor
la source
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.

Gilberto
la source
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'

yemu
la source
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])
rumpel
la source
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()
Martin Alexandersson
la source
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)]
Rishabh Vij
la source