将分组的数据帧分为单独的数据帧

时间:2018-11-29 18:23:40

标签: python pandas

我想获取一个已分组的数据框,并为每个组分别创建单独的数据框。

我正在使用列表推导,使用列表names_list中的值来切片熊猫数据帧,然后将结果分配给同名变量。但是,names_list中的值并不总是出现在我的数据框中,并且哪个不会出现在数据框中是完全随机的。我该如何进行这项工作,只返回实际出现的变量?

我尝试过的事情:

idx = pd.IndexSlice

names_list = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
a, b, c, d, e, f, g, h = [df.loc[idx[x,:],:] for x in names_list]

只要数据帧中不存在任何值,以上代码都会返回KeyError。

也尝试过:

def split_df(data):
    try:
        a = [df.loc[idx[x,:],:] for x in data]
    except KeyError:
        a = None
    return a


names_list = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
a, b, c, d, e, f, g, h = [x for x in names_list]
name_vars = [a, b, c, d, e, f, g, h]

name_vars_2 = []
for var, val in zip(name_vars,names_list):
    var = split_df(val)
    if var is None:
        continue
    else:
        name_vars_2.append(var)

这种方法只会为每个值返回无列表。

我想要的结果是一个变量列表,并将数据帧的各个部分分配给每个变量。

2 个答案:

答案 0 :(得分:4)

设置

df = pd.DataFrame(dict(A=range(10), B=[*'aabbccddee']))

dict

将它们存储在字典中,而不是命名变量中

d = dict((*df.groupby('B'),))

d['a']

   A  B
0  0  a
1  1  a

d['d']

   A  B
6  6  d
7  7  d

不推荐!

但是为了您的教育。您可以更新locals()字典。
这很糟糕,因为动态污染名称空间将导致许多难以跟踪的错误。
实际上,不能保证会做任何事情。

Per Docs

  

注意:请勿修改此词典的内容;更改可能不会影响解释器使用的局部变量和自由变量的值。

免责声明,这是您可以执行的操作:

locals().update(dict((*df.groupby('B'),)))

然后访问命名变量

a

   A  B
0  0  a
1  1  a

d

   A  B
6  6  d
7  7  d

答案 1 :(得分:0)

根据数据本身,以下方法应该起作用。

from string import ascii_lowercase, ascii_uppercase
import pandas as pd 
import numpy as np 

n0, n1 = 8, 3
midx = pd.MultiIndex.from_product([list(ascii_lowercase[:n0]),
                                   list(ascii_uppercase[:n1])])
columns = ['foo', 'bar']
arr = np.arange(n0*n1*len(columns)).reshape((len(midx),len(columns)))
all_df = pd.DataFrame(arr, index=midx, columns=columns)
sub_df = all_df.query('foo < 12 or foo > 16').query('foo < 42')
vals = lambda df, idx, l: {c: df.loc[idx[c, :], :] for c in l}

与其显式分配变量,不如使用字典并查看结果,因为它们将出现在整个数据集中,并且删除了一个数据块。

all_vals = vals(all_df, pd.IndexSlice, list(ascii_lowercase[:n0]))
sub_vals = vals(sub_df, pd.IndexSlice, list(ascii_lowercase[:n0]))

例如

>>> all_vals['a']
     foo  bar
a A    0    1
  B    2    3
  C    4    5

>>> sub_vals['a']
     foo  bar
a A    0    1
  B    2    3
  C    4    5

但是

>>> all_vals['c']
     foo  bar
c A   12   13
  B   14   15
  C   16   17

>>> sub_vals['c']
Empty DataFrame
Columns: [foo, bar]
Index: []

最后,您可以使用[... for x in lst if x in df.index.levels[0].values]之类的内容过滤理解,并可能将值存储在collections.defaultdict中,并根据需要进行初始化。