web-dev-qa-db-fra.com

Fractionnement de dataframe en plusieurs dataframes

J'ai une très grande trame de données (environ 1 million de lignes) avec les données d'une expérience (60 répondants) ... Je voudrais scinder la trame en 60 trames de données (une trame pour chaque participant) 

Dans le cadre de données (appelé = données), il existe une variable appelée "nom", qui est le code unique de chaque participant.

J'ai essayé ce qui suit, mais rien ne se passe (ou le ne s'arrête pas dans l'heure). Ce que j'ai l'intention de faire est de scinder le dataframe (données) en de plus petits dataframes et de les ajouter à une 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

Je ne reçois pas de message d'erreur, le script semble fonctionner pour toujours!

Y a-t-il un moyen intelligent de le faire?

48

Tout d’abord, votre approche est inefficace car l’ajout à la liste, ligne par ligne, sera lent car il faut agrandir périodiquement la liste lorsque l’espace disponible pour la nouvelle entrée est insuffisant; avant et alloué une fois.

Cependant, je pense fondamentalement que votre approche est un peu inutile car vous avez déjà un cadre de données, alors pourquoi en créer un nouveau pour chacun de ces utilisateurs?

Je voudrais trier le dataframe par la colonne 'name', définir l'index pour être ceci et si nécessaire ne pas supprimer la colonne.

Générez ensuite une liste de toutes les entrées uniques, puis vous pouvez effectuer une recherche à l'aide de ces entrées et surtout si vous interrogez uniquement les données, utilisez le critère de sélection pour renvoyer une vue sur le cadre de données sans générer une copie de données coûteuse.

Alors:

# 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'

MODIFIER

sort est maintenant obsolète, vous devez utiliser sort_values maintenant:

# 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

Puis-je demander pourquoi ne pas simplement le faire en découpant le bloc de données. Quelque chose comme

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

Bonjour, vous avez un dictionnaire de trames de données exactement comme (je pense) que vous voulez Besoin d'accéder à un? Il suffit d'entrer

DataFrameDict['Joe']

J'espère que cela pourra aider

44
Woody Pride

Vous pouvez convertir groupby object en tuples et ensuite en dict:

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

Facile:

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

En plus de la réponse de Gusev Slava, vous pouvez utiliser les groupes de groupby:

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

Cela donnera un dictionnaire avec les clés que vous avez regroupées et pointant vers les partitions correspondantes. L'avantage est que les clés sont maintenues et ne disparaissent pas dans l'index de la liste.

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

Voici une méthode groupby (et vous pouvez appliquer une application arbitraire plutôt qu'une somme)

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)

Somme est cythonisée c'est pourquoi c'est si rapide

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

La méthode basée sur la compréhension de la liste et sur la groupby- qui stocke toutes les données fractionnées dans une variable de liste et peut être consultée à l'aide de l'index.

Exemple

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

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

Vous pouvez utiliser la commande groupby si vous avez déjà des étiquettes pour vos données.

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

Voici un exemple détaillé:

Supposons que nous voulions partitionner une série pd à l'aide de certaines étiquettes en une liste de morceaux. Par exemple, in_series est:

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

Et son label_series correspondant est:

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

Courir

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

qui retourne out_list une list de deux pd.Series:

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

Notez que vous pouvez utiliser certains paramètres de in_series lui-même pour regrouper la série, par exemple in_series.index.day

0
idnavid