การแยก dataframe เป็นหลาย ๆ dataframes


93

ฉันมีดาต้าเฟรมขนาดใหญ่มาก (ประมาณ 1 ล้านแถว) พร้อมข้อมูลจากการทดสอบ (ผู้ตอบ 60 คน)

ฉันต้องการแบ่ง dataframe ออกเป็น 60 dataframes (dataframe สำหรับผู้เข้าร่วมแต่ละคน)

ในดาต้าเฟรมdataมีตัวแปรที่เรียกว่า'name'ซึ่งเป็นรหัสเฉพาะสำหรับผู้เข้าร่วมแต่ละคน

ฉันได้ลองทำสิ่งต่อไปนี้แล้ว แต่ไม่มีอะไรเกิดขึ้น (หรือการดำเนินการไม่หยุดภายในหนึ่งชั่วโมง) สิ่งที่ฉันตั้งใจจะทำคือการแบ่งออกdataเป็นดาต้าเฟรมที่เล็กลงและต่อท้ายรายการ ( 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

ฉันไม่ได้รับข้อความแสดงข้อผิดพลาดดูเหมือนว่าสคริปต์จะทำงานตลอดไป!

มีวิธีที่ชาญฉลาดในการทำหรือไม่?

คำตอบ:


53

ประการแรกแนวทางของคุณไม่มีประสิทธิภาพเนื่องจากการต่อท้ายรายการในแต่ละแถวจะช้าเนื่องจากต้องขยายรายการเป็นระยะเมื่อมีพื้นที่ไม่เพียงพอสำหรับรายการใหม่ความเข้าใจในรายการจะดีกว่าในแง่นี้เนื่องจากขนาดถูกกำหนดขึ้น ด้านหน้าและจัดสรรครั้งเดียว

อย่างไรก็ตามฉันคิดว่าโดยพื้นฐานแล้วแนวทางของคุณค่อนข้างสิ้นเปลืองเนื่องจากคุณมี dataframe อยู่แล้วทำไมต้องสร้างใหม่สำหรับผู้ใช้แต่ละคนเหล่านี้

ฉันจะจัดเรียง dataframe ตามคอลัมน์'name'ตั้งค่าดัชนีให้เป็นแบบนี้และถ้าจำเป็นอย่าวางคอลัมน์

จากนั้นสร้างรายการของรายการที่ไม่ซ้ำกันทั้งหมดจากนั้นคุณสามารถทำการค้นหาโดยใช้รายการเหล่านี้และที่สำคัญอย่างยิ่งหากคุณค้นหาข้อมูลเท่านั้นให้ใช้เกณฑ์การเลือกเพื่อส่งคืนมุมมองบนดาต้าเฟรมโดยไม่ต้องมีสำเนาข้อมูลที่มีราคาแพง

ใช้pandas.DataFrame.sort_valuesและ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'

74

ฉันถามได้ไหมว่าทำไมไม่ทำโดยการแบ่งกรอบข้อมูล สิ่งที่ต้องการ

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

สวัสดีคุณมีพจนานุกรมของ data frames เหมือนกับที่ (ฉันคิดว่า) คุณต้องการ ต้องการเข้าถึงหรือไม่ เพียงแค่ใส่

DataFrameDict['Joe']

หวังว่าจะช่วยได้


39

คุณสามารถแปลงgroupbyวัตถุเป็นtuplesแล้วเป็น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

ไม่แนะนำแต่เป็นไปได้ที่จะสร้าง DataFrames ตามกลุ่ม:

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 สามารถช่วยคุณ:

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

จากนั้นคุณสามารถทำงานกับแต่ละกลุ่มได้เช่นเดียวกับดาต้าเฟรมสำหรับผู้เข้าร่วมแต่ละคน และ DataFrameGroupBy อ็อบเจ็กต์เมธอดเช่น (ใช้, แปลง, รวม, head, first, last) ส่งคืนอ็อบเจ็กต์ DataFrame

หรือคุณสามารถสร้างรายการgroupedและรับ DataFrame ทั้งหมดโดยดัชนี:

l_grouped = list(grouped)

l_grouped[0][1] - DataFrame สำหรับกลุ่มแรกที่มีชื่อจริง


7

นอกจากคำตอบของ Gusev Slava แล้วคุณอาจต้องการใช้กลุ่มของ groupby:

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

สิ่งนี้จะให้พจนานุกรมที่มีคีย์ที่คุณจัดกลุ่มโดยชี้ไปที่พาร์ติชันที่เกี่ยวข้อง ข้อดีคือคีย์จะได้รับการดูแลและไม่หายไปในดัชนีรายการ


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

นี่เป็นวิธีการจัดกลุ่ม (และคุณสามารถสมัครได้โดยพลการแทนที่จะเป็นผลรวม)

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 เป็น cythonized นั่นคือสาเหตุที่มันเร็วมาก

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

วิธีการขึ้นอยู่กับความเข้าใจรายการและ groupby - ซึ่งเก็บดาต้าเฟรมแยกทั้งหมดในตัวแปรรายการและสามารถเข้าถึงได้โดยใช้ดัชนี

ตัวอย่าง

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

ans[0]
ans[0].column_name

1
  • ขั้นแรกวิธีการใน OP ใช้งานได้ แต่ไม่มีประสิทธิภาพ อาจดูเหมือนว่าจะทำงานตลอดไปเนื่องจากชุดข้อมูลมีความยาว
  • ใช้.groupbyใน'method'คอลัมน์และสร้างdictการDataFramesมีที่ไม่ซ้ำกันค่าเป็นกุญแจที่มี 'method'dict-comprehension
    • .groupbyส่งคืนgroupbyอ็อบเจ็กต์ที่มีข้อมูลเกี่ยวกับกลุ่มซึ่งgเป็นค่าที่ไม่ซ้ำกันใน'method'แต่ละกลุ่มและdเป็นค่าDataFrameสำหรับกลุ่มนั้น
  • valueของแต่ละkeyในdf_dictจะเป็นซึ่งสามารถเข้าถึงได้ในวิธีมาตรฐานDataFramedf_dict['key']
  • คำถามเดิมต้องการlistของDataFramesซึ่งสามารถทำได้ด้วยlist-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) หรือ df_dict['Astrometry'].head(3)
  • มี 2 ​​กลุ่มนี้เท่านั้น
         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) หรือ 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) หรือ 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

อีกทางหนึ่ง

  • นี่เป็นวิธีการสร้างแบบแมนนวลDataFramesโดยใช้แพนด้า: การจัดทำดัชนีบูลีน
  • สิ่งนี้คล้ายกับคำตอบที่ยอมรับแต่.locไม่จำเป็น
  • DataFramesนี้เป็นวิธีการที่ได้รับการยอมรับสำหรับการสร้างเสริมคู่
  • วิธี pythonic ในการสร้างวัตถุหลายคือโดยการวางไว้ในภาชนะ (เช่นdict, list,generatorฯลฯ ) ที่แสดงข้างต้น
df1 = df[df.method == 'Astrometry']
df2 = df[df.method == 'Eclipse Timing Variations']

0

คุณสามารถใช้คำสั่ง groupby หากคุณมีป้ายกำกับสำหรับข้อมูลของคุณอยู่แล้ว

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

นี่คือตัวอย่างโดยละเอียด:

สมมติว่าเราต้องการแบ่งชุด pd โดยใช้ป้ายกำกับบางรายการในรายการชิ้นส่วนตัวอย่างเช่นin_series:

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

และสิ่งที่สอดคล้องกันlabel_seriesคือ:

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

วิ่ง

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

ซึ่งจะส่งคืนout_listหนึ่งlistในสอง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]

โปรดทราบว่าคุณสามารถใช้พารามิเตอร์บางin_seriesตัวเพื่อจัดกลุ่มซีรีส์ได้เช่นin_series.index.day


-1

ฉันมีปัญหาที่คล้ายกัน ฉันมีชุดเวลาขายประจำวันสำหรับร้านค้า 10 ร้านที่แตกต่างกันและ 50 รายการที่แตกต่างกัน ฉันต้องการแบ่งดาต้าเฟรมดั้งเดิมใน 500 ดาต้าเฟรม (10 ร้านค้า * 50 ร้านค้า) เพื่อใช้โมเดลแมชชีนเลิร์นนิงกับแต่ละแบบ แต่ฉันไม่สามารถทำได้ด้วยตนเอง

นี่คือส่วนหัวของ dataframe:

ส่วนหัวของดาต้าเฟรม: df

ฉันได้สร้างสองรายการ; หนึ่งสำหรับชื่อของดาต้าเฟรมและอีกชื่อหนึ่งสำหรับอาร์เรย์ [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])

และเมื่อทั้งสองรายการพร้อมแล้วคุณสามารถวนซ้ำเพื่อสร้างดาต้าเฟรมที่คุณต้องการ:

         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)

ด้วยวิธีนี้ฉันได้สร้าง 500 dataframes

หวังว่านี่จะเป็นประโยชน์!

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.