Tách khung dữ liệu thành nhiều khung dữ liệu


92

Tôi có một khung dữ liệu rất lớn (khoảng 1 triệu hàng) với dữ liệu từ một thử nghiệm (60 người trả lời).

Tôi muốn chia dataframe thành 60 dataframe (một khung dữ liệu cho mỗi người tham gia).

Trong khung dữ liệu, datacó một biến được gọi 'name', là mã duy nhất cho mỗi người tham gia.

Tôi đã thử những cách sau, nhưng không có gì xảy ra (hoặc quá trình thực hiện không dừng lại trong vòng một giờ). Những gì tôi định làm là chia datanhỏ thành các khung dữ liệu nhỏ hơn và nối chúng vào một danh sách ( 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

Tôi không nhận được thông báo lỗi, tập lệnh dường như chạy mãi mãi!

Có một cách thông minh để làm điều đó?

Câu trả lời:


53

Thứ nhất, cách tiếp cận của bạn không hiệu quả vì việc bổ sung vào danh sách theo hàng sẽ chậm vì nó phải phát triển danh sách theo định kỳ khi không có đủ không gian cho mục nhập mới, khả năng hiểu danh sách tốt hơn về mặt này khi kích thước được xác định trước và được phân bổ một lần.

Tuy nhiên, tôi nghĩ về cơ bản cách tiếp cận của bạn hơi lãng phí vì bạn đã có một khung dữ liệu, vậy tại sao phải tạo một khung dữ liệu mới cho từng người dùng này?

Tôi sẽ sắp xếp khung dữ liệu theo cột 'name', đặt chỉ mục là cái này và nếu cần, không bỏ cột.

Sau đó, tạo danh sách tất cả các mục nhập duy nhất và sau đó bạn có thể thực hiện tra cứu bằng cách sử dụng các mục nhập này và quan trọng là nếu bạn chỉ truy vấn dữ liệu, hãy sử dụng tiêu chí lựa chọn để trả về chế độ xem trên khung dữ liệu mà không phải chịu một bản sao dữ liệu tốn kém.

Sử dụng pandas.DataFrame.sort_valuespandas.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'

74

Tôi có thể hỏi tại sao không chỉ làm điều đó bằng cách cắt khung dữ liệu. Cái gì đó như

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

Này trước khi bạn có một từ điển khung dữ liệu giống như (tôi nghĩ) bạn muốn chúng. Cần truy cập một? Chỉ cần nhập

DataFrameDict['Joe']

Hy vọng điều đó sẽ giúp


38

Bạn có thể chuyển đổi groupbyđối tượng thành tuplesvà sau đó thành 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

Nó không được khuyến khích , nhưng có thể tạo DataFrames theo nhóm:

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


16

Groupby có thể giúp bạn:

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

Sau đó, bạn có thể làm việc với từng nhóm như với khung dữ liệu cho từng người tham gia. Và các phương thức đối tượng DataFrameGroupBy như (áp dụng, biến đổi, tổng hợp, đầu, đầu tiên, cuối cùng) trả về một đối tượng DataFrame.

Hoặc bạn có thể tạo danh sách groupedvà lấy tất cả DataFrame theo chỉ mục:

l_grouped = list(grouped)

l_grouped[0][1] - DataFrame cho nhóm đầu tiên có tên.


7

Ngoài câu trả lời của Gusev Slava, bạn có thể muốn sử dụng các nhóm của groupby:

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

Thao tác này sẽ mang lại một từ điển với các khóa bạn đã nhóm, trỏ đến các phân vùng tương ứng. Ưu điểm là các khóa được duy trì và không biến mất trong chỉ mục danh sách.


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

Đây là một cách nhóm (và bạn có thể áp dụng tùy ý thay vì tính tổng)

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 được mạng hóa đó là lý do tại sao điều này rất nhanh

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

1

Phương pháp dựa trên khả năng hiểu danh sách và groupby- Lưu trữ tất cả khung dữ liệu được phân tách trong biến danh sách và có thể được truy cập bằng cách sử dụng chỉ mục.

Thí dụ

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

ans[0]
ans[0].column_name

1
  • Đầu tiên, phương thức trong OP hoạt động, nhưng không hiệu quả. Nó có thể đã chạy mãi mãi, vì tập dữ liệu đã dài.
  • Sử dụng .groupbytrên 'method'cột và tạo một dicttrong các giá trị DataFramesduy nhất 'method'làm khóa, với a dict-comprehension.
    • .groupbytrả về một groupbyđối tượng, chứa thông tin về các nhóm, ở đâu glà giá trị duy nhất 'method'cho mỗi nhóm và dlà giá trị cho nhóm DataFrameđó.
  • Các valuetừng keydf_dict, sẽ là một DataFrame, mà có thể được truy cập trong cách tiêu chuẩn, df_dict['key'].
  • Các câu hỏi ban đầu muốn có một listsố DataFrames, có thể được thực hiện với mộtlist-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) hoặc là df_dict['Astrometry'].head(3)
  • Chỉ có 2 trong nhóm này
         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) hoặc là 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) hoặc là 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

Ngoài ra

  • Đây là một phương pháp thủ công để tạo riêng biệt DataFramesbằng cách sử dụng gấu trúc: Boolean Indexing
  • Điều này tương tự với câu trả lời được chấp nhận , nhưng .lockhông bắt buộc.
  • Đây là một phương pháp có thể chấp nhận được để tạo thêm một vài DataFrames.
  • Cách pythonic để tạo ra nhiều đối tượng, là bằng cách đặt chúng trong một container (ví dụ như dict, list, generator, vv), như trình bày ở trên.
df1 = df[df.method == 'Astrometry']
df2 = df[df.method == 'Eclipse Timing Variations']

0

Bạn có thể sử dụng lệnh groupby, nếu bạn đã có một số nhãn cho dữ liệu của mình.

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

Đây là một ví dụ chi tiết:

Giả sử chúng ta muốn phân vùng một chuỗi pd bằng cách sử dụng một số nhãn thành một danh sách các phần. Ví dụ in_series: là:

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

Và tương ứng của nó label_serieslà:

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

Chạy

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

trả về out_listmột listtrong hai 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]

Lưu ý rằng bạn có thể sử dụng một số tham số từ in_serieschính nó để nhóm chuỗi, ví dụ:in_series.index.day


-1

Tôi đã có vấn đề tương tự. Tôi đã có một chuỗi thời gian bán hàng hàng ngày cho 10 cửa hàng khác nhau và 50 mặt hàng khác nhau. Tôi cần chia khung dữ liệu ban đầu thành 500 khung dữ liệu (10 cửa hàng * 50 cửa hàng) để áp dụng các mô hình Học máy cho từng khung dữ liệu đó và tôi không thể thực hiện theo cách thủ công.

Đây là phần đầu của khung dữ liệu:

người đứng đầu khung dữ liệu: df

Tôi đã tạo hai danh sách; một cho tên của khung dữ liệu và một cho một vài mảng [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])

Và khi hai danh sách đã sẵn sàng, bạn có thể lặp lại chúng để tạo khung dữ liệu mà bạn muốn:

         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)

Bằng cách này, tôi đã tạo 500 khung dữ liệu.

Hy vọng điều này sẽ hữu ích!

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.