Pandas:如何迭代第一级并从第2级随机选择然后将子选择添加到数据框

时间:2015-06-10 09:47:55

标签: python pandas

我刚刚从熊猫开始,可能已经咬过的东西比我可以咀嚼的多。我有一个带有MultiIndex的Dataframe,我希望在第一个('type')级别上循环,然后从第二个('lwc')级别的值中随机选择,然后创建一个子Dataframe然后我将这个子选择添加到另一个Dataframe中。

数据框为spec_df,其级别名称为:

spec_df.columns.names
FrozenList([u'type', u'lwc', u'rad', u'cl_top', u'wvc', u'aot', u'press', u'sza', u'phi0', u'umu', u'phi'])

到目前为止我的代码:

rand_clds = pd.DataFrame([])

for l1 in spec_df.columns.levels[0]:
    l2l = spec_df[l1].columns.levels[0]
    rand_l2 = np.random.choice(l2l)
    rand_clds[l1, rand_l2] = spec_df.ix[[l1, rand_l2]]

一直运行到循环的开始。 l2l包含级别'lwc'的所有值,而不仅仅是l1'type'的子集。

2 个答案:

答案 0 :(得分:2)

假设spec_df如下所示:

In [141]: spec_df
Out[141]: 
      foo bar foo baz    bar
        A   B   B   C  A   D
        1   2   3   1  2   3
baz C   2   2   9   6  8   5
    D   7   8   0   6  7   8
qux C   3   8   6   9  2   3
    D   1   2   6   2  9   8
    C   5   8   4   8  9   1

然后,您可以通过将元组列表传递给spec_df来进行子选择。对于 例如,如果cols等于

In [140]: cols
Out[140]: [('baz', 'A', '2'), ('foo', 'B', '3'), ('bar', 'D', '3')]

然后

In [147]: spec_df[cols]
Out[147]: 
      baz foo bar
        A   B   D
        2   3   3
baz C   8   9   5
    D   7   0   8
qux C   2   6   3
    D   9   6   8
    C   9   4   1

这将解决如何选择子DataFrame的问题,如果可能的话 构造cols。事实证明,使用普通的Python并不是那么难。只是 收集dict中的列,将第一列级别值映射到 全列元组:

columns = spec_df.columns
seen = dict()
for col in columns:
    seen.setdefault(col[0], []).append(col)
# >>> seen
# {'bar': [('bar', 'B', '2'), ('bar', 'D', '3')],
#  'baz': [('baz', 'C', '1'), ('baz', 'A', '2')],
#  'foo': [('foo', 'A', '1'), ('foo', 'B', '3')]}

然后使用random.choice为每个键选择一个列元组 seen

cols = [random.choice(seen[firstcol]) for firstcol in seen]

全部放在一起:

import random
import numpy as np
import pandas as pd
random.seed(1)
spec_df = pd.DataFrame(
    np.random.randint(10, size=(5,6)),
    columns=pd.MultiIndex.from_arrays([['foo','bar','foo','baz','baz','bar'],
                                       list('ABBCAD'),
                                   list('123123')]),
    index=pd.MultiIndex.from_arrays([['baz']*2+['qux']*3,
                                     list('CDCDC')]))

columns = spec_df.columns
seen = dict()
for col in columns:
    seen.setdefault(col[0], []).append(col)
cols = [random.choice(seen[firstcol]) for firstcol in seen]
print(spec_df[cols])

产量

      baz foo bar
        A   B   D
        2   3   3
baz C   8   9   5
    D   7   0   8
qux C   2   6   3
    D   9   6   8
    C   9   4   1

答案 1 :(得分:0)

这并不完全回答我自己的问题。我把它留给天才,它会有一个。这里只是为第一级I循环的每个值选择第一列。不理想,但是,它给了我一些东西:

rand_clds = pd.DataFrame([])

for l1 in spec_df.columns.levels[0]:
    rand_clds[l1] = spec_df[l1].icol(0)

问题是rand_clds数据框没有原始数据帧的列名等。我至少可以用这个来绘制一些东西。