Pandas创建一个具有随机值的多索引DataFrame



我有以下多索引DataFrame。

import pandas as pd
import numpy as np
# Create df ---
names = ['add', 'sub', 'mul', 'divi'] # List of the names of our maths functions
size = 4
tups = [('scalars', 'add', 'sc0'), ('scalars', 'add', 'sc1'), ('scalars', 'add', 'sc2'), ('scalars', 'sub', 'sc0'), ('scalars', 'sub', 'sc1'), ('scalars', 'mul', 'sc0'), ('scalars', 'mul', 'sc1'), ('scalars', 'mul', 'sc2'), ('scalars', 'divi', 'sc0'), ('scalars', 'divi', 'sc1'), ('operator', '', '')]
df = pd.DataFrame(columns=pd.MultiIndex.from_tuples(tups))
df['operatorIndex'] = np.random.randint(0, len(names), size)
df['operator'] = df['operatorIndex'].apply(lambda x: str(names[x]))
groupSize = 2
df['ID']=np.divmod(np.arange(len(df)),groupSize)[0]+1
df.set_index('ID', inplace=True)
df.sort_index(inplace=True)
> df
scalars                                   operator  operatorIndex
add         sub     mul         divi        
sc0 sc1 sc2 sc0 sc1 sc0 sc1 sc2 sc0 sc1     
ID                                              
1   NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN   mul       2
1   NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN   add       0
2   NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN   sub       1
2   NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN   mul       2

如何仅将随机整数(介于0和100之间(分配给与每行的operator列中的值相关的sc列?优选地,这将在没有任何循环的情况下进行。

一个例子可能看起来像

> df
scalars                                   operator  operatorIndex
add         sub     mul         divi        
sc0 sc1 sc2 sc0 sc1 sc0 sc1 sc2 sc0 sc1     
ID                                              
1   NaN NaN NaN NaN NaN 7   3   9   NaN NaN   mul       2
1   29  12  11  NaN NaN NaN NaN NaN NaN NaN   add       0
2   NaN NaN NaN 6   36  NaN NaN NaN NaN NaN   sub       1
2   NaN NaN NaN NaN NaN 16  2   29  NaN NaN   mul       2

首先,屏蔽第二列级别(df.columns.get_level_values(level=1)(与运算符列值(df['operator'](一致的值。这可以通过将两者转换为numpy数组(使用to_numpy方法(和利用numpy广播来实现。

mask = df.columns.get_level_values(level=1).to_numpy() == df['operator'].to_numpy()[:, None]

然后将此掩码传递给DataFrame.mask,并使用0到100之间的随机整数更新True值的位置。

res = df.mask(mask, np.random.randint(0, 101, size=df.shape))

输出

# Given the input df
>>> df 
scalars                                              operator operatorIndex
add            sub       mul           divi                            
sc0  sc1  sc2  sc0  sc1  sc0  sc1  sc2  sc0  sc1                       
ID                                                                            
1      NaN  NaN  NaN  NaN  NaN  NaN  NaN  NaN  NaN  NaN      mul             2
1      NaN  NaN  NaN  NaN  NaN  NaN  NaN  NaN  NaN  NaN      add             0
2      NaN  NaN  NaN  NaN  NaN  NaN  NaN  NaN  NaN  NaN      sub             1
2      NaN  NaN  NaN  NaN  NaN  NaN  NaN  NaN  NaN  NaN      mul             2
>>> mask 
[[False False False False False  True  True  True False False False False]
[ True  True  True False False False False False False False False False]
[False False False  True  True False False False False False False False]
[False False False False False  True  True  True False False False False]]
>>> res
add            sub       mul           divi                            
sc0  sc1  sc2  sc0  sc1  sc0  sc1  sc2  sc0  sc1                       
ID                                                                            
1      NaN  NaN  NaN  NaN  NaN    2   79   17  NaN  NaN      mul             2
1       15   16   30  NaN  NaN  NaN  NaN  NaN  NaN  NaN      add             0
2      NaN  NaN  NaN   35   94  NaN  NaN  NaN  NaN  NaN      sub             1
2      NaN  NaN  NaN  NaN  NaN   11   95   48  NaN  NaN      mul             2

最新更新