Membagi kerangka data menjadi beberapa kerangka data

92

Saya memiliki kerangka data yang sangat besar (sekitar 1 juta baris) dengan data dari percobaan (60 responden).

Saya ingin membagi kerangka data menjadi 60 kerangka data (kerangka data untuk setiap peserta).

Dalam dataframe, dataterdapat variabel yang disebut 'name'kode unik untuk setiap peserta.

Saya telah mencoba yang berikut ini, tetapi tidak ada yang terjadi (atau eksekusi tidak berhenti dalam satu jam). Apa yang ingin saya lakukan adalah membaginya datamenjadi kerangka data yang lebih kecil, dan menambahkannya ke list ( 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

Saya tidak mendapatkan pesan kesalahan, skrip sepertinya berjalan selamanya!

Apakah ada cara cerdas untuk melakukannya?

Martin Petri Bagger
sumber

Jawaban:

53

Pertama, pendekatan Anda tidak efisien karena penambahan ke daftar secara berurutan akan lambat karena harus mengembangkan daftar secara berkala ketika tidak ada cukup ruang untuk entri baru, pemahaman daftar lebih baik dalam hal ini karena ukurannya ditentukan depan dan dialokasikan sekali.

Namun, saya pikir pada dasarnya pendekatan Anda sedikit sia-sia karena Anda sudah memiliki kerangka data, jadi mengapa membuat yang baru untuk masing-masing pengguna ini?

Saya akan mengurutkan dataframe berdasarkan kolom 'name', mengatur indeks menjadi ini dan jika diperlukan tidak menjatuhkan kolom.

Kemudian buat daftar semua entri unik dan kemudian Anda dapat melakukan pencarian menggunakan entri ini dan yang terpenting jika Anda hanya meminta data, gunakan kriteria pemilihan untuk mengembalikan tampilan pada kerangka data tanpa menimbulkan salinan data yang mahal.

Gunakan pandas.DataFrame.sort_valuesdan pandas.DataFrame.set_index:

# 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'
EdChum
sumber
74

Dapatkah saya bertanya mengapa tidak melakukannya dengan memotong bingkai data. Sesuatu seperti

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

Hai, presto Anda memiliki kamus bingkai data seperti yang (menurut saya) Anda inginkan. Perlu mengaksesnya? Masuk saja

DataFrameDict['Joe']

Semoga membantu

Woody Pride
sumber
38

Anda dapat mengonversi groupbyobjek menjadi tuplesdan kemudian menjadi 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

Ini tidak disarankan , tetapi mungkin membuat DataFrames menurut grup:

for i, g in df.groupby('Name'):
    globals()['df_' + str(i)] =  g

print (df_a)
  Name  A  B  C
0    a  4  7  1
1    a  5  8  3
jezrael
sumber
17

Mudah:

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

Groupby dapat membantu Anda:

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

Kemudian Anda dapat bekerja dengan setiap kelompok seperti dengan kerangka data untuk setiap peserta. Dan metode objek DataFrameGroupBy seperti (apply, transform, aggregate, head, first, last) mengembalikan objek DataFrame.

Atau Anda dapat membuat daftar dari groupeddan mendapatkan semua DataFrame dengan indeks:

l_grouped = list(grouped)

l_grouped[0][1] - DataFrame untuk grup pertama dengan nama depan.

Gusev Slava
sumber
7

Selain jawaban Gusev Slava, Anda mungkin ingin menggunakan grup groupby:

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

Ini akan menghasilkan kamus dengan kunci yang telah Anda kelompokkan, menunjuk ke partisi yang sesuai. Keuntungannya adalah bahwa kunci dipertahankan dan tidak hilang dalam indeks daftar.

Quickbeam2k1
sumber
3
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

Berikut cara groupby (dan Anda bisa melakukan penerapan sewenang-wenang daripada menjumlahkan)

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)

Sum di-cythonized itu sebabnya ini sangat cepat

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
Jeff
sumber
1

Metode berdasarkan pemahaman daftar dan groupby - Yang menyimpan semua dataframe yang terpisah dalam variabel daftar dan dapat diakses menggunakan indeks.

Contoh

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

ans[0]
ans[0].column_name
Ram Prajapati
sumber
1
  • Pertama, metode dalam OP berfungsi, tetapi tidak efisien. Ini mungkin tampak berjalan selamanya, karena datasetnya panjang.
  • Gunakan .groupbypada 'method'kolom, dan buat dictdari DataFramesdengan 'method'nilai unik sebagai kuncinya, dengan a dict-comprehension.
    • .groupbymengembalikan groupbyobjek, yang berisi informasi tentang kelompok, di mana gadalah nilai unik di 'method'setiap kelompok, dan dadalah DataFrameuntuk kelompok itu.
  • Masing value-masing keymasuk df_dict, akan menjadi DataFrame, yang dapat diakses dengan cara standar df_dict['key'],.
  • Pertanyaan awal menginginkan listdari DataFrames, yang dapat dilakukan denganlist-comprehension
    • df_list = [d for _, d in df.groupby('method')]
import pandas as pd
import seaborn as sns  # for test dataset

# load data for example
df = sns.load_dataset('planets')

# display(df.head())
            method  number  orbital_period   mass  distance  year
0  Radial Velocity       1         269.300   7.10     77.40  2006
1  Radial Velocity       1         874.774   2.21     56.95  2008
2  Radial Velocity       1         763.000   2.60     19.84  2011
3  Radial Velocity       1         326.030  19.40    110.62  2007
4  Radial Velocity       1         516.220  10.50    119.47  2009


# Using a dict-comprehension, the unique 'method' value will be the key
df_dict = {g: d for g, d in df.groupby('method')}

print(df_dict.keys())
[out]:
dict_keys(['Astrometry', 'Eclipse Timing Variations', 'Imaging', 'Microlensing', 'Orbital Brightness Modulation', 'Pulsar Timing', 'Pulsation Timing Variations', 'Radial Velocity', 'Transit', 'Transit Timing Variations'])

# or a specific name for the key, using enumerate (e.g. df1, df2, etc.)
df_dict = {f'df{i}': d for i, (g, d) in enumerate(df.groupby('method'))}

print(df_dict.keys())
[out]:
dict_keys(['df0', 'df1', 'df2', 'df3', 'df4', 'df5', 'df6', 'df7', 'df8', 'df9'])
  • df_dict['df1].head(3) atau df_dict['Astrometry'].head(3)
  • Hanya ada 2 di grup ini
         method  number  orbital_period  mass  distance  year
113  Astrometry       1          246.36   NaN     20.77  2013
537  Astrometry       1         1016.00   NaN     14.98  2010
  • df_dict['df2].head(3) atau df_dict['Eclipse Timing Variations'].head(3)
                       method  number  orbital_period  mass  distance  year
32  Eclipse Timing Variations       1         10220.0  6.05       NaN  2009
37  Eclipse Timing Variations       2          5767.0   NaN    130.72  2008
38  Eclipse Timing Variations       2          3321.0   NaN    130.72  2008
  • df_dict['df3].head(3) atau df_dict['Imaging'].head(3)
     method  number  orbital_period  mass  distance  year
29  Imaging       1             NaN   NaN     45.52  2005
30  Imaging       1             NaN   NaN    165.00  2007
31  Imaging       1             NaN   NaN    140.00  2004

kalau tidak

  • Ini adalah metode manual untuk membuat pandas terpisah DataFramesmenggunakan : Boolean Indexing
  • Ini mirip dengan jawaban yang diterima , tetapi .loctidak diwajibkan.
  • Ini adalah metode yang dapat diterima untuk membuat pasangan ekstra DataFrames.
  • Cara pythonic untuk membuat beberapa objek, adalah dengan menempatkan mereka dalam sebuah wadah (misalnya dict, list, generator, dll), seperti yang ditunjukkan di atas.
df1 = df[df.method == 'Astrometry']
df2 = df[df.method == 'Eclipse Timing Variations']
Trenton McKinney
sumber
0

Anda dapat menggunakan perintah groupby, jika Anda sudah memiliki beberapa label untuk data Anda.

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

Berikut contoh detailnya:

Katakanlah kita ingin mempartisi seri pd menggunakan beberapa label ke dalam daftar potongan Misalnya, in_seriesadalah:

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

Dan yang sesuai label_seriesadalah:

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

Lari

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

yang mengembalikan out_lista listdari dua 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]

Perhatikan bahwa Anda dapat menggunakan beberapa parameter dari in_seriesdirinya sendiri untuk mengelompokkan rangkaian, misalnya,in_series.index.day

idnavid
sumber
-1

Saya memiliki masalah yang sama. Saya memiliki rangkaian waktu penjualan harian untuk 10 toko berbeda dan 50 item berbeda. Saya perlu membagi kerangka data asli menjadi 500 kerangka data (10 toko * 50 toko) untuk menerapkan model Pembelajaran Mesin ke masing-masing kerangka dan saya tidak dapat melakukannya secara manual.

Ini adalah kepala kerangka data:

kepala kerangka data: df

Saya telah membuat dua daftar; satu untuk nama dataframe dan satu untuk pasangan array [item_number, store_number].

    list=[]
    for i in range(1,len(items)*len(stores)+1):
    global list
    list.append('df'+str(i))

    list_couple_s_i =[]
    for item in items:
          for store in stores:
                  global list_couple_s_i
                  list_couple_s_i.append([item,store])

Dan setelah kedua daftar siap, Anda dapat mengulanginya untuk membuat kerangka data yang Anda inginkan:

         for name, it_st in zip(list,list_couple_s_i):
                   globals()[name] = df.where((df['item']==it_st[0]) & 
                                                (df['store']==(it_st[1])))
                   globals()[name].dropna(inplace=True)

Dengan cara ini saya telah membuat 500 dataframe.

Semoga bermanfaat!

Luigi Bungaro
sumber