我刚刚从熊猫开始,可能已经咬过的东西比我可以咀嚼的多。我有一个带有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'
的子集。
答案 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
数据框没有原始数据帧的列名等。我至少可以用这个来绘制一些东西。