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

时间:2013-11-05 14:01:13

标签: python split pandas dataframe

我有一个非常大的数据框(大约100万行),包含来自实验的数据(60位受访者)。 我想将数据帧拆分为60个数据帧(每个参与者的数据帧)。

在数据框(称为= data)中有一个名为'name'的变量,它是每个参与者的唯一代码。

我尝试过以下操作,但没有任何反应(或者在一小时内没有停止)。我打算做的是将数据帧(数据)拆分成更小的数据帧并将它们附加到列表(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

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

有没有聪明的方法呢?

12 个答案:

答案 0 :(得分:50)

我可以问为什么不通过切片数据框来做到这一点。像

这样的东西
#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']

希望有所帮助

答案 1 :(得分:39)

首先,你的方法是低效的,因为在新的条目没有足够的空间时,必须定期增加列表,因此逐行附加到列表中的速度会很慢,因此列表推导在这方面更好预先确定并分配一次。

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

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

然后生成所有唯一条目的列表,然后您可以使用这些条目执行查找,并且至关重要的是,如果您只查询数据,请使用选择标准返回数据框上的视图,而不会产生代价高昂的数据副本。 / p>

所以:

# sort the dataframe
df.sort(columns=['name'], 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'

修改

sort现已弃用,您现在需要使用sort_values

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

答案 2 :(得分:31)

您可以将groupby对象转换为selenium.common.exceptions.WebDriverException: Message: Unable to find a matching set of capabilities ,然后转换为tuples

dict

它不是recommended,但可以按组创建DataFrame:

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

答案 3 :(得分:11)

Groupby可以帮助您:

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

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

或者您可以从grouped制作列表,并按索引获取所有DataFrame:

l_grouped = list(grouped) l_grouped[0][1] - 具有名字的第一个组的DataFrame。

答案 4 :(得分:7)

简单:

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

答案 5 :(得分:4)

除了Gusev Slava的回答,您可能还想使用groupby的小组:

     element.all(by.css('.settings__group .settings__sub-title')).count().then(function(count)
            {
                for(var j = 0; j < count;j++)
                {
                      console.log('first loop ' + j);
                      browser.sleep(2000);
                element.all(by.className('settings__group')).get(j).all(by.className('settings__item')).count().then(function (c) {


                for (let i = 0; i < c; i++) {
                        console.log('second loop ' + i);
                    browser.sleep(1000);
                    element.all(by.className('settings__group')).get(j).all(by.className('settings__item')).get(i).click();
                    browser.sleep(1000);
                    element(by.id('crValidationButton')).isPresent().then(function (present) {
                        if (present) {
                            element(by.id('crValidationButton')).click();
                            browser.sleep(2000);
                            v.validationCase();
                            browser.sleep(2000);
                        }
                        else {
                            browser.sleep(2000);
                            v.validationCase();
                            browser.sleep(2000);
                        }
                    });
                    browser.sleep(1500);
                }
            });
                }
            });

这将产生一个字典,其中包含您分组的键,指向相应的分区。优点是密钥保持不变并且不会在列表索引中消失。

答案 6 :(得分: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

这是一种groupby方式(你可以做任意的应用而不是总和)

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是cython化的,这就是为什么这么快

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

答案 7 :(得分:1)

基于列表理解和groupby的方法-将所有拆分数据帧存储在列表变量中,并且可以使用索引进行访问。

示例

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

ans[0]
ans[0].column_name

答案 8 :(得分:1)

  • 首先,OP中的方法有效,但效率不高。由于数据集很长,它似乎可以永远运行。
  • 'method'列上使用.groupby,并使用唯一的dict值作为键,并创建一个DataFrames的{​​{1}},其中{{3} }。
    • 'method'返回一个.groupby对象,该对象包含有关组的信息,其中groupbyg中每个组的唯一值,而'method'是该组的d
  • DataFrame中每个value的{​​{1}}将是一个key,可以通过标准方式df_dict进行访问。
  • 最初的问题需要DataFrame中的df_dict['key'],可以通过dict-comprehension完成
    • list
DataFrames
  • 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'])
  • 该组中只有2个
df_dict['df1].head(3)
  • df_dict['Astrometry'].head(3) 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)

或者

  • 这是使用NASA Exoplanets创建单独的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的可接受方法。
  • 创建多个对象的pythonic方法是将它们放置在容器中(例如.locDataFramesdict等),如上所示。
list

答案 9 :(得分: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_listlist中的两个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

答案 10 :(得分:0)

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

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_dict 的结果是 dict,这意味着可以像这样访问每个 DataFrame:

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

答案 11 :(得分:-1)

我有类似的问题。我有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个数据帧。

希望这会有所帮助!