【问题标题】:Applying dataframe-returning function to every row of base dataframe将数据帧返回函数应用于基础数据帧的每一行
【发布时间】:2017-12-05 13:01:06
【问题描述】:

玩具示例

假设base_df 是如下所示的微小数据框:

In [221]: base_df
Out[221]: 
     seed
I S      
0 a     0
  b     1
1 a     2
  b     3

请注意,base_df 具有用于行的 2 级多索引。 (这里的部分问题涉及在派生数据框中“传播”这个多索引的值。)

现在,函数fn(在本文末尾给出的定义)接受一个整数seed 作为参数,并返回一个由字符串键索引的一列数据帧1。例如:

In [222]: fn(0)
Out[222]: 
              F
key            
01011  0.592845
10100  0.844266

In [223]: fn(1)
Out[223]: 
              F
key            
11110  0.997185
01000  0.932557
11100  0.128124

我想通过将fn 应用于base_df 的每一行并将生成的数据帧垂直连接来生成一个新的数据帧。更具体地说,期望的结果如下所示:

                  F
I S key            
0 a 01011  0.592845
    10100  0.844266
  b 11110  0.997185
    01000  0.932557
    11100  0.128124
1 a 01101  0.185082
    01110  0.931541
  b 00100  0.070725
    11011  0.839949
    11111  0.121329
    11000  0.569311

IOW,从概念上讲,所需的数据帧是通过为base_df 的每一行生成一个“子数据帧”,并将这些子数据帧垂直连接起来获得的。每行对应的子数据框有一个3级多索引。此多索引的前两个级别(IS)来自 base_df 的该行的多索引值,而其最后一个级别(key)以及(单独)F 列来自 fn 返回的数据框,用于该行的 seed 值。

我不清楚的部分是如何将行的原始多索引值传播到由fn 为该行的seed 值创建的数据帧的行。

重要提示:我正在寻找一种与base_df 的多索引级别的名称及其编号无关的方法。


我尝试了以下

base_df.apply(lambda row: fn(row.seed), axis=1)

...但是评估失败并出现错误

ValueError: Shape of passed values is (4, 2), indices imply (4, 1)

有什么方便的方法来做我想做的事吗?


这是fn 的定义。就这个问题而言,它的内部结构并不重要。重要的是它需要一个整数 seed 作为参数,并返回一个数据帧,如前所述。

import numpy
def fn(seed, _spec='{{0:0{0:d}b}}'.format(5)):
    numpy.random.seed(int(seed))
    n = numpy.random.randint(2, 5)
    r = numpy.random.rand(n)
    k = map(_spec.format, numpy.random.randint(0, 31, size=n))
    result = pandas.DataFrame(r, columns=['F'], index=k)
    result.index.name = 'key'
    return result

1 在这个例子中,这些键恰好对应于 0 到 31 之间的某个整数的二进制表示,包括 0 和 31,但这个事实在问题中没有任何作用。

【问题讨论】:

    标签: python pandas group-by apply pandas-groupby


    【解决方案1】:

    选项 1
    groupby

    base_df.groupby(level=[0, 1]).apply(fn)
    
                      F
    I S key            
    0 a 11010  0.385245
        00010  0.890244
        00101  0.040484
      b 01001  0.569204
        11011  0.802265
        00100  0.063107
    1 a 00100  0.947827
        00100  0.056551
        11000  0.084872
      b 11110  0.592641
        00110  0.130423
        11101  0.915945
    

    选项 2
    pd.concat

    pd.concat({t.Index: fn(t.seed) for t in base_df.itertuples()})
    
                      F
        key            
    0 a 11011  0.592845
        00011  0.844266
      b 00101  0.997185
        01111  0.932557
        00000  0.128124
    1 a 01011  0.185082
        10010  0.931541
      b 10011  0.070725
        01010  0.839949
        01011  0.121329
        11001  0.569311
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-01-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多