Teilen Sie einen großen Pandas-Datenrahmen


86

Ich habe einen großen Datenrahmen mit 423244 Zeilen. Ich möchte dies in 4 aufteilen. Ich habe den folgenden Code ausprobiert, der einen Fehler ergab.ValueError: array split does not result in an equal division

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

Wie kann man diesen Datenrahmen in 4 Gruppen aufteilen?


Wir wollen np.split(df, N)bitte eine Funktion.
Sören

Antworten:


182

Verwendung 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]

Vielen Dank! Darüber hinaus möchte ich auf jede Gruppe eine Funktion anwenden: Wie kann ich nacheinander auf Gruppen zugreifen?
Nilani Algiriyage

7
@NilaniAlgiriyage - array_splitgibt eine Liste von DataFrames zurück, so dass Sie einfach die Liste durchlaufen können ...
root

Ich teile den Datenrahmen auf, da er zu groß ist. Ich möchte die erste Gruppe nehmen und die Funktion anwenden, dann die zweite Gruppe und die Funktion anwenden usw. Wie kann ich auf jede Gruppe zugreifen?
Nilani Algiriyage

1
Wie erhalten Sie keinen AttributeError, da Dataframe keine 'Größe' hat?
Boosted_d16

2
Diese Antwort ist veraltet:AttributeError: 'DataFrame' object has no attribute 'size'
Tjorriemorrie

33

Ich wollte dasselbe tun und hatte zuerst Probleme mit der Split-Funktion, dann Probleme mit der Installation von Pandas 0.15.2. Also ging ich zurück zu meiner alten Version und schrieb eine kleine Funktion, die sehr gut funktioniert. Ich hoffe das kann helfen!

# 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
viel schneller als mit np.array_split ()
jgaw

4
Die richtige Methode zur Berechnung von numberChunks importieren math numberChunks = math.ceil (len (df) / chunkSize)
Sergey Leyko

21

Ich denke , jetzt können wir schlicht verwenden ilocmit rangedafür.

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
Einfach und intuitiv
rmstmppr

13

np.array_split(df, 3)Beachten Sie, dass der Datenrahmen in drei Unterdatenrahmen aufgeteilt wird, während die split_dataframein der Antwort von @ elixir definierte Funktion beim Aufrufen als split_dataframe(df, chunk_size=3)den Datenrahmen alle chunk_sizeZeilen aufteilt .

Beispiel:

Mit 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)

... Sie erhalten 3 Unterdatenrahmen:

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

Mit split_dataframe:

df_split2 = split_dataframe(df, chunk_size=3)

... Sie erhalten 4 Unterdatenrahmen:

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

Hoffe ich habe recht und das ist nützlich.


Gibt es eine einfache Möglichkeit, diesen Prozess zufällig zu gestalten? Ich kann nur daran denken, eine Rondom-Spalte hinzuzufügen, die zufällige Spalte zu teilen und zu entfernen, aber es könnte einen einfacheren Weg geben
Rutger Hofste

Müssen sie gleich groß sein?
InquilineKea

8

Vorsicht:

np.array_splitfunktioniert nicht mit numpy-1.9.0. Ich habe ausgecheckt: Es funktioniert mit 1.8.1.

Error:

Der Datenrahmen hat kein Attribut "Größe"


6
Ich habe einen Fehler im Pandas Github gemeldet: Github.com/pydata/pandas/issues/8846 scheint bereits für Pandas 0.15.2
Yemu

4

Sie können groupbyFolgendes verwenden , vorausgesetzt, Sie haben einen ganzzahligen Index:

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)]

Hinweis: groupbyGibt ein Tupel zurück, in dem das 2. Element der Datenrahmen ist, daher die etwas komplizierte Extraktion.

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

1

Ich habe auch festgestellt, dass np.array_split nicht mit Pandas DataFrame funktioniert. Meine Lösung bestand darin, nur den Index des DataFrame zu teilen und dann eine neue Spalte mit der Bezeichnung "group" einzuführen:

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

Dies macht groubige Operationen sehr bequem, zum Beispiel die Berechnung des Mittelwerts jeder Gruppe:

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

0

Sie können Listenverständnisse verwenden, um dies in einer einzelnen Zeile zu tun

n = 4
chunks = [df[i:i+n] for i in range(0,df.shape[0],n)]
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.