将数据框拆分为多个数据框

2024-12-11 08:47:00
admin
原创
137
摘要:问题描述:我有一个非常大的数据框(大约 100 万行),其中包含来自实验的数据(60 位受访者)。我想将数据框分成 60 个数据框(每个参与者一个数据框)。在数据框中data,有一个名为的变量'name',它是每个参与者的唯一代码。我尝试了以下操作,但什么也没发生(或者执行在一小时内没有停止)。我打算将拆分d...

问题描述:

我有一个非常大的数据框(大约 100 万行),其中包含来自实验的数据(60 位受访者)。

我想将数据框分成 60 个数据框(每个参与者一个数据框)。

在数据框中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

我没有收到错误消息,脚本似乎永远运行下去!

有没有聪明的办法来做到这一点?


解决方案 1:

我可以问一下为什么不直接通过切分数据框来实现。比如

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

解决方案 2:

首先,您的方法效率低下,因为逐行附加到列表会很慢,因为当新条目的空间不足时,它必须定期增加列表,而列表理解在这方面更好,因为大小是预先确定并分配一次。

但是,我认为从根本上来说您的方法有点浪费,因为您已经有数据框了,那么为什么要为每个用户创建一个新的数据框呢?

我将按列对数据框进行排序'name',将索引设置为该索引,并且如果需要则不删除该列。

然后生成所有唯一条目的列表,然后您可以使用这些条目执行查找,并且至关重要的是,如果您仅查询数据,请使用选择条件返回数据框上的视图,而不会产生昂贵的数据复制。

使用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'

解决方案 3:

简单的:

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

解决方案 4:

您可以将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

解决方案 5:

Groupby 可以帮助您:

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

然后,您可以像处理每个参与者的数据框一样处理每个组。DataFrameGroupBy 对象方法(例如 (apply、transform、aggregate、head、first、last))返回一个 DataFrame 对象。

或者您可以列出列表grouped并通过索引获取所有 DataFrame:

l_grouped = list(grouped)

l_grouped[0][1]- 具有名字的第一个组的 DataFrame。

解决方案 6:

除了 Gusev Slava 的答案之外,您可能还想使用 groupby 的群组:

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

这将生成一个包含您分组所依据的键的字典,指向相应的分区。优点是键会保留下来,不会在列表索引中消失。

解决方案 7:

  • OP 中的方法有效,但效率不高。它可能似乎永远运行下去,因为数据集很长。

  • .groupby在列上使用'method',并创建一个dict具有DataFrames唯一'method'值作为键的,其中dict-comprehension

    • .groupby返回一个groupby对象,其中包含有关组的信息,其中g是每个组的唯一值'method'dDataFrame该组的。

  • value每个的将是,可以通过标准方式访问。key`df_dictDataFramedf_dict['key']`

  • 最初的问题想要一个listDataFrames可以用一个来完成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
  • 有关 seaborn数据集的更多信息

    • 美国宇航局系外行星

或者

  • DataFrames这是使用pandas手动创建单独的方法:布尔索引

  • 这与接受的答案类似,但.loc不是必需的。

  • 这是创建几个额外内容的可接受方法DataFrames

  • 创建多个对象的 Python 方式是将它们放在一个容器中(例如,,,dict等等),如上所示。list`generator`

df1 = df[df.method == 'Astrometry']
df2 = df[df.method == 'Eclipse Timing Variations']

解决方案 8:

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

解决方案 9:

该方法基于列表理解,groupby将所有分割数据框存储在列表变量中,可以使用索引进行访问。

例子

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

ans[0]
ans[0].column_name

解决方案 10:

如果您已经为数据设置了一些标签,则可以使用 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

解决方案 11:

这里有一个可能对某些人有帮助的小功能(效率可能不完美,但紧凑+或多或少容易理解):

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]

解决方案 12:

现有的答案涵盖了所有好的情况,并很好地解释了对象如何groupby像一个字典,其键和值可以通过 访问.groups。然而,还有更多方法可以完成与现有答案相同的工作:

  • 通过解包 groupby 对象并将其转换为字典来创建列表:

dict([*df.groupby('Name')]) # same as dict(list(df.groupby('Name')))
  • 创建一个元组+字典(这与@jezrael 的答案相同):

dict((*df.groupby('Name'),))
  • 如果我们只想要 DataFrames,我们可以获取字典的值(上面创建):

[*dict([*df.groupby('Name')]).values()]

解决方案 13:

我遇到了类似的问题。我有 10 家不同商店和 50 种不同商品的每日销售时间序列。我需要将原始数据框拆分为 500 个数据框(10 家商店 * 50 家商店),以便将机器学习模型应用于每个数据框,而我无法手动完成。

这是数据框的头部:

数据框的头部: 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 个数据框。

希望这会有所帮助!

相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   1565  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1354  
  信创国产芯片作为信息技术创新的核心领域,对于推动国家自主可控生态建设具有至关重要的意义。在全球科技竞争日益激烈的背景下,实现信息技术的自主可控,摆脱对国外技术的依赖,已成为保障国家信息安全和产业可持续发展的关键。国产芯片作为信创产业的基石,其发展水平直接影响着整个信创生态的构建与完善。通过不断提升国产芯片的技术实力、产...
国产信创系统   21  
  信创生态建设旨在实现信息技术领域的自主创新和安全可控,涵盖了从硬件到软件的全产业链。随着数字化转型的加速,信创生态建设的重要性日益凸显,它不仅关乎国家的信息安全,更是推动产业升级和经济高质量发展的关键力量。然而,在推进信创生态建设的过程中,面临着诸多复杂且严峻的挑战,需要深入剖析并寻找切实可行的解决方案。技术创新难题技...
信创操作系统   27  
  信创产业作为国家信息技术创新发展的重要领域,对于保障国家信息安全、推动产业升级具有关键意义。而国产芯片作为信创产业的核心基石,其研发进展备受关注。在信创国产芯片的研发征程中,面临着诸多复杂且艰巨的难点,这些难点犹如一道道关卡,阻碍着国产芯片的快速发展。然而,科研人员和相关企业并未退缩,积极探索并提出了一系列切实可行的解...
国产化替代产品目录   28  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用