codememo

데이터 프레임을 여러 데이터 프레임으로 분할

tipmemo 2023. 10. 30. 21:00
반응형

데이터 프레임을 여러 데이터 프레임으로 분할

저는 매우 큰 데이터 프레임(약 100만 행)과 실험(60명의 응답자)의 데이터를 가지고 있습니다.

데이터 프레임을 60개의 데이터 프레임(참가자별 데이터 프레임)으로 나누고 싶습니다.

데이터 프레임에서,data, 라는 변수가 있습니다.'name', 각 참가자의 고유 코드입니다.

다음을 시도해 보았지만 아무 일도 일어나지 않습니다(또는 실행이 1시간 이내에 중지되지 않음).내가 하려는 것은 그들을 분열시키는 것입니다.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

오류 메시지가 표시되지 않습니다. 스크립트가 영원히 실행되는 것 같습니다!

현명한 방법이 있습니까?

왜 그냥 데이터 프레임을 잘라내서 하지 않는지 물어봐도 될까요?뭐 이런 거.

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

예, 데이터 프레임에 대한 사전이 필요한 것처럼 있습니다.접속할 필요가 있습니까?그냥들어가기

DataFrameDict['Joe']

첫째, 새로운 엔트리를 위한 공간이 부족할 때 주기적으로 리스트를 늘려야 하기 때문에 행 단위로 리스트에 첨부하는 것이 더 느리기 때문에 당신의 접근 방식은 비효율적입니다. 이 점에서 리스트를 미리 크기를 정하고 한 번 할당하기 때문에 리스트를 이해하는 것이 더 낫습니다.

하지만 이미 데이터 프레임을 가지고 있기 때문에 근본적으로 귀하의 접근 방식은 약간 낭비적이라고 생각합니다. 그런데 왜 이러한 사용자 각각에 대해 새 프레임을 만들까요?

열별로 데이터 프레임을 정렬하겠습니다.'name', 인덱스를 이 값으로 설정하고 필요한 경우 열을 떨어뜨리지 마십시오.

그런 다음 모든 고유한 항목의 목록을 생성한 다음 이러한 항목을 사용하여 조회를 수행할 수 있으며, 데이터만 쿼리하는 경우에는 선택 기준을 사용하여 값비싼 데이터 복사본을 발생시키지 않고 데이터 프레임에 대한 보기를 반환할 수 있습니다.

사용 및 :

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

개체를 다음으로 변환할 수 있습니다.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

권장되지 않지만 그룹별로 데이터 프레임을 생성할 수 있습니다.

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

쉬운:

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

Groupby는 다음을 지원합니다.

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

그러면 참가자별 데이터 프레임처럼 각 그룹과 함께 작업할 수 있습니다.그리고 DataFrameGroupBy(적용, 변환, 집계, 머리, 처음, 마지막)와 같은 객체 방식으로 DataFrame 객체를 반환합니다.

또는 목록을 만들 수 있습니다.grouped인덱스별로 모든 DataFrame을 가져옵니다.

l_grouped = list(grouped)

l_grouped[0][1]- 이름이 있는 첫 번째 그룹의 DataFrame입니다.

Gusev Slava의 답변 외에도 groupby의 그룹을 사용할 수 있습니다.

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

이렇게 하면 그룹화된 키가 있는 해당 파티션을 가리키는 사전이 생성됩니다.키가 유지되고 목록 색인에서 사라지지 않는 것이 장점입니다.

  • OP의 방법은 효과는 있지만 효율적이지는 않습니다.데이터셋이 길었기 때문에 영원히 실행되는 것처럼 보였을 수도 있습니다.
  • 사용처'method'열을 만들고 a를 만듭니다.dictDataFrames독특한'method'값을 키로 지정합니다.
    • .groupby답례품 agroupbyobject, 그룹에 대한 정보를 포함하며, 여기서g는 의 고유 값입니다.'method'그룹별로, 그리고d. ㅇDataFrame그 그룹을 위해서.
  • value각각의key인에df_dict, 가 될 것입니다.DataFrame, 일반적인 방법으로 접근할 수 있고,df_dict['key'].
  • 원래 질문은.listDataFrames, 그것은 a로 할 수 있습니다.
    • 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.
  • 여러 개체를 만드는 파이톤적인 방법은 개체를 용기에 넣는 것입니다.dict,list,generator (),.
df1 = df[df.method == 'Astrometry']
df2 = df[df.method == 'Eclipse Timing Variations']
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은 cytonized 되어있고 그래서 이것이 매우 빠른 이유입니다.

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

리스트 이해에 기반한 방법 및groupby- 모든 분할 데이터 프레임을 목록 변수에 저장하고 인덱스를 사용하여 액세스할 수 있습니다.

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

ans[0]
ans[0].column_name

데이터에 대한 레이블이 이미 있는 경우 명령별 그룹을 사용할 수 있습니다.

 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 a 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

일부에게 도움이 될 수 있는 작은 기능이 있습니다(효율성은 완벽하지 않지만 콤팩트한 + 어느 정도 이해하기 쉽습니다).

def get_splited_df_dict(df: 'pd.DataFrame', split_column: 'str'):
    """
    splits a pandas.DataFrame on split_column and returns it as a dict
    """

    df_dict = {value: df[df[split_column] == value].drop(split_column, axis=1) for value in df[split_column].unique()}

    return df_dict

주어진 열에서 각각의 고유 값을 선택하고 모든 엔트리를 별도의 DataFrame에 넣음으로써 DataFrame을 여러 DataFrame으로 변환합니다..drop(split_column, axis=1)는 DataFrame을 분할하는 데 사용된 열을 제거하기 위한 것입니다.제거는 필요하지 않지만, 수술 후 메모리 사용량을 줄이는 데 조금 도움이 될 수 있습니다.

의 결과get_splited_df_dictdict, 즉, 다음과 같이 각 DataFrame에 액세스할 수 있습니다.

splitted = get_splited_df_dict(some_df, some_column)
# accessing the DataFrame with 'some_column_value'
splitted[some_column_value]

기존의 답변들은 모든 좋은 사례들을 포함하고 있으며, 그 방법을 꽤 잘 설명하고 있습니다.groupby객체는 키와 값이 있는 사전과 같습니다..groups. 그러나 기존 답변과 동일한 작업을 수행하는 더 많은 방법은 다음과 같습니다.

  • 개체별로 그룹을 풀고 사전에 캐스팅하여 목록을 만듭니다.
dict([*df.groupby('Name')]) # same as dict(list(df.groupby('Name')))
  • 튜플 + dict 만들기 (@jezrail의 답변과 동일):
dict((*df.groupby('Name'),))
  • DataFrame만 원한다면 사전의 값(위에서 작성)을 얻을 수 있습니다.
[*dict([*df.groupby('Name')]).values()]

저도 비슷한 문제가 있었습니다.저는 10개의 다양한 매장과 50개의 다양한 품목에 대한 일일 판매 타임 시리즈를 가졌습니다.원래 데이터 프레임을 500개의 데이터 프레임(10개의 스토어*50개의 스토어)으로 나누어 머신 러닝 모델을 각각 적용해야 했고, 수작업으로는 할 수 없었습니다.

다음은 데이터 프레임의 헤드입니다.

head of the 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개의 데이터 프레임을 만들었습니다.

이것이 도움이 되기를 바랍니다!

언급URL : https://stackoverflow.com/questions/19790790/splitting-dataframe-into-multiple-dataframes

반응형