wake-up-neo.com

Datenframe in mehrere Datenframes aufteilen

Ich habe einen sehr großen Datenrahmen (etwa 1 Million Zeilen) mit Daten aus einem Experiment (60 Befragte) ..__ Ich möchte den Datenrahmen in 60 Datenrahmen (einen Datenrahmen für jeden Teilnehmer) aufteilen. 

Im Datenrahmen (genannt = data) gibt es eine Variable namens 'name', die den eindeutigen Code für jeden Teilnehmer darstellt.

Ich habe folgendes versucht, aber es passiert nichts (oder das hört nicht innerhalb einer Stunde auf). Was ich vorhabe, ist das Aufteilen des Datenrahmens (der Daten) in kleinere Datenrahmen und das Anhängen an eine Liste (Datalist):

import pandas as pd

def splitframe(data, name='name'):

    n = data[name][0]

    df = pd.DataFrame(columns=data.columns)

    datalist = []

    for i in range(len(data)):
        if data[name][i] == n:
            df = df.append(data.iloc[i])
        else:
            datalist.append(df)
            df = pd.DataFrame(columns=data.columns)
            n = data[name][i]
            df = df.append(data.iloc[i])

    return datalist

Ich erhalte keine Fehlermeldung, das Skript scheint für immer zu laufen!

Gibt es einen intelligenten Weg, dies zu tun?

48

Erstens ist Ihr Ansatz ineffizient, da das Anhängen an die Liste in einer Reihe nach Basis langsam ist, da die Liste periodisch erweitert werden muss, wenn für den neuen Eintrag nicht genügend Platz vorhanden ist. Listenverstehen sind in dieser Hinsicht besser, da die Größe bestimmt wird vorne und einmal vergeben.

Ich denke jedoch, dass Ihr Ansatz grundsätzlich ein wenig verschwenderisch ist, da Sie bereits einen Datenrahmen haben. Warum also für jeden dieser Benutzer einen neuen erstellen?

Ich würde den Datenrahmen nach Spalte 'name' sortieren, den Index auf diesen Wert setzen und die Spalte bei Bedarf nicht löschen.

Dann generieren Sie eine Liste aller eindeutigen Einträge, und Sie können eine Suche mit diesen Einträgen durchführen. Wenn Sie nur die Daten abfragen, verwenden Sie die Auswahlkriterien, um eine Ansicht des Datenrahmens zurückzugeben, ohne eine kostspielige Datenkopie zu verursachen.

So:

# sort the dataframe
df.sort(columns=['name'], inplace=True)
# set the index to be this and don't drop
df.set_index(keys=['name'], drop=False,inplace=True)
# get a list of names
names=df['name'].unique().tolist()
# now we can perform a lookup on a 'view' of the dataframe
joe = df.loc[df.name=='joe']
# now you can query all 'joes'

BEARBEITEN

sort ist nun veraltet, Sie müssen jetzt sort_values verwenden:

# sort the dataframe
df.sort_values(by='name', axis=1, inplace=True)
# set the index to be this and don't drop
df.set_index(keys=['name'], drop=False,inplace=True)
# get a list of names
names=df['name'].unique().tolist()
# now we can perform a lookup on a 'view' of the dataframe
joe = df.loc[df.name=='joe']
# now you can query all 'joes'
36
EdChum

Kann ich fragen, warum nicht einfach der Datenrahmen durchgeschnitten wird? So etwas wie

#create some data with Names column
data = pd.DataFrame({'Names': ['Joe', 'John', 'Jasper', 'Jez'] *4, 'Ob1' : np.random.Rand(16), 'Ob2' : np.random.Rand(16)})

#create unique list of names
UniqueNames = data.Names.unique()

#create a data frame dictionary to store your data frames
DataFrameDict = {elem : pd.DataFrame for elem in UniqueNames}

for key in DataFrameDict.keys():
    DataFrameDict[key] = data[:][data.Names == key]

Hey Presto, Sie haben ein Wörterbuch mit Datenrahmen, so wie Sie (ich glaube) wollen. Benötigen Sie einen Zugang? Einfach eintreten

DataFrameDict['Joe']

Hoffentlich hilft das

44
Woody Pride

Sie können groupby object in tuples und dann in dict konvertieren:

df = pd.DataFrame({'Name':list('aabbef'),
                   'A':[4,5,4,5,5,4],
                   'B':[7,8,9,4,2,3],
                   'C':[1,3,5,7,1,0]}, columns = ['Name','A','B','C'])

print (df)
  Name  A  B  C
0    a  4  7  1
1    a  5  8  3
2    b  4  9  5
3    b  5  4  7
4    e  5  2  1
5    f  4  3  0

d = dict(Tuple(df.groupby('Name')))
print (d)
{'b':   Name  A  B  C
2    b  4  9  5
3    b  5  4  7, 'e':   Name  A  B  C
4    e  5  2  1, 'a':   Name  A  B  C
0    a  4  7  1
1    a  5  8  3, 'f':   Name  A  B  C
5    f  4  3  0}

print (d['a'])
  Name  A  B  C
0    a  4  7  1
1    a  5  8  3
28
jezrael

Groupby kann Ihnen helfen:

grouped = data.groupby(['name'])

Dann können Sie mit jeder Gruppe wie mit einem Datenrahmen für jeden Teilnehmer arbeiten. Und DataFrameGroupBy-Objektmethoden wie (Apply, Transform, Aggregate, Head, First, Last) geben ein DataFrame-Objekt zurück.

Oder Sie können eine Liste aus grouped erstellen und alle DataFrames nach Index abrufen:

l_grouped = list(grouped)

l_grouped[0][1] - DataFrame für die erste Gruppe mit dem Vornamen.

12
Gusev Slava

Einfach:

    [v for k, v in df.groupby('name')]
6
Daniel Braun

Zusätzlich zu der Antwort von Gusev Slava können Sie die Gruppen von groupby verwenden:

{key: df.loc[value] for key, value in df.groupby("name").groups.items()}

Daraufhin wird ein Wörterbuch mit den von Ihnen gruppierten Schlüsseln angezeigt, die auf die entsprechenden Partitionen zeigen. Der Vorteil ist, dass die Schlüssel im Listenindex erhalten bleiben und nicht verschwinden.

3
Quickbeam2k1
In [28]: df = DataFrame(np.random.randn(1000000,10))

In [29]: df
Out[29]: 
<class 'pandas.core.frame.DataFrame'>
Int64Index: 1000000 entries, 0 to 999999
Data columns (total 10 columns):
0    1000000  non-null values
1    1000000  non-null values
2    1000000  non-null values
3    1000000  non-null values
4    1000000  non-null values
5    1000000  non-null values
6    1000000  non-null values
7    1000000  non-null values
8    1000000  non-null values
9    1000000  non-null values
dtypes: float64(10)

In [30]: frames = [ df.iloc[i*60:min((i+1)*60,len(df))] for i in xrange(int(len(df)/60.) + 1) ]

In [31]: %timeit [ df.iloc[i*60:min((i+1)*60,len(df))] for i in xrange(int(len(df)/60.) + 1) ]
1 loops, best of 3: 849 ms per loop

In [32]: len(frames)
Out[32]: 16667

Hier ist ein Groupby-Weg (und Sie können eine beliebige Anwendung statt einer Summe ausführen)

In [9]: g = df.groupby(lambda x: x/60)

In [8]: g.sum()    

Out[8]: 
<class 'pandas.core.frame.DataFrame'>
Int64Index: 16667 entries, 0 to 16666
Data columns (total 10 columns):
0    16667  non-null values
1    16667  non-null values
2    16667  non-null values
3    16667  non-null values
4    16667  non-null values
5    16667  non-null values
6    16667  non-null values
7    16667  non-null values
8    16667  non-null values
9    16667  non-null values
dtypes: float64(10)

Summe ist cythonisiert, deshalb ist das so schnell

In [10]: %timeit g.sum()
10 loops, best of 3: 27.5 ms per loop

In [11]: %timeit df.groupby(lambda x: x/60)
1 loops, best of 3: 231 ms per loop
3
Jeff

Die auf Listenverständnis und groupby basierende Methode, die alle aufgeteilten Datenframes in der Listenvariablen speichert und über den Index zugänglich ist.

Beispiel

ans = [pd.DataFrame(y) for x, y in DF.groupby('column_name', as_index=False)]

ans[0]
ans[0].column_name
0
Ram Prajapati

Sie können den Befehl groupby verwenden, wenn Sie bereits Beschriftungen für Ihre Daten haben.

 out_list = [group[1] for group in in_series.groupby(label_series.values)]

Hier ist ein detailliertes Beispiel:

Angenommen, wir möchten eine pd-Reihe mit einigen Bezeichnungen in eine Liste von Chunks unterteilen. Beispiel: in_series lautet:

2019-07-01 08:00:00   -0.10
2019-07-01 08:02:00    1.16
2019-07-01 08:04:00    0.69
2019-07-01 08:06:00   -0.81
2019-07-01 08:08:00   -0.64
Length: 5, dtype: float64

Und sein entsprechender label_series ist:

2019-07-01 08:00:00   1
2019-07-01 08:02:00   1
2019-07-01 08:04:00   2
2019-07-01 08:06:00   2
2019-07-01 08:08:00   2
Length: 5, dtype: float64

Lauf

out_list = [group[1] for group in in_series.groupby(label_series.values)]

das gibt out_list ein list von zwei pd.Series zurück:

[2019-07-01 08:00:00   -0.10
2019-07-01 08:02:00   1.16
Length: 2, dtype: float64,
2019-07-01 08:04:00    0.69
2019-07-01 08:06:00   -0.81
2019-07-01 08:08:00   -0.64
Length: 3, dtype: float64]

Beachten Sie, dass Sie einige Parameter von in_series selbst verwenden können, um die Reihe zu gruppieren, z. B. in_series.index.day.

0
idnavid