【问题标题】:Python Pandas: returning more then one field value when applying function to a data frame rowPython Pandas:将函数应用于数据框行时返回一个以上的字段值
【发布时间】:2023-03-09 03:31:01
【问题描述】:

我需要对数据框行应用几个函数。这些函数的参数从单行的两个或多个字段中获取值。例如:

d = {                                                                                                       
  'a': [1,1,1,1],                                                                                           
  'b': [2,2,2,2],                                                                                           
  'c': [3,3,3,3],                                                                                           
  'd': [4,4,4,4]                                                                                            
}                                                                                                           

df1 = pd.DataFrame(d)                                                                                       

def f1(x,y):                                                                                                
    return x + 2*y                                                                                          

def f2(x,y):                                                                                                
    return y + 2*x                                                                                          

df2 = pd.DataFrame()                                                                                        
df2['val1'] = df1.apply(lambda r: f1(r.a, r.b),1)                                                           
df2['val2'] = df1.apply(lambda r: f2(r.c, r.d),1)                                                           

当依次应用每个函数时,Pandas 会对所有数据框行进行单独的迭代。在此示例中,Pandas 将数据帧迭代两次。结果我得到:

In [10]: df2                                                                                                
Out[10]:                                                                                                    
   val1  val2                                                                                               
0     5    10                                                                                               
1     5    10                                                                                               
2     5    10                                                                                               
3     5    10                                                                                               

有什么方法可以在单次传递数据帧中应用两个或多个这样的函数?这样,应用程序应该连续返回一个以上字段的值。此外,这种情况包括应用单个函数返回多个字段的值。如何做到这一点?

【问题讨论】:

    标签: python pandas dataframe


    【解决方案1】:

    您可以通过组合您的功能同时填充它们:

    def f3(x,y,z,a):
        return x + 2*y, a + 2*z
    df3 = pd.DataFrame()
    df3['val1'], df3['val2'] = f3(df1.a, df1.b, df1.c, df1.d)
    

    【讨论】:

    • 这是一个很好的方法,但并不是每个函数都可以像这样在 dataFrame 上运行。也可以像df3['val1'], df3['val2'] = f1(df1.a, df1.b), f2(df1.c, df1.d)
    • 不适用于我的真实函数和参数。我收到此错误:'/Users/user/usr/anaconda_2.7/anaconda/lib/python2.7/site-packages/pandas/core/generic.pyc in __getattr__(self, name) 2670 if name in self._info_axis : 2671 return self[name] -> 2672 return object.__getattribute__(self, name) 2673 2674 def __setattr__(self, name, value): AttributeError: 'Series' object has no attribute 'split' '
    【解决方案2】:

    如果你的函数是线性的或者可以以某种方式向量化,我们可以做很多很酷的事情。

    t = pd.DataFrame(dict(val1=[1, 2, 0, 0], val2=[0, 0, 2, 1]), df1.columns)
    df1.dot(t)
    

    甚至更快

    pd.DataFrame(
        df1.values.dot(
            np.array([[1, 0], [2, 0], [0, 2], [0, 1]])
        ),
        df1.index,
        ['val1', 'val2']
    )
    

    或者你可以定义一个新的函数来应用

    def f3(r):
        return pd.Series(dict(val1=f1(r.a, r.b), val2=f2(r.c, r.d)))
    
    df1.apply(f3, 1)
    

    【讨论】:

    • 在我的 MacBookPro6,2,英特尔酷睿 i5, 2,53,处理器:1,核心:2,L2 缓存(每个核心):256 KB,L3 缓存上尝试了这个:3 MB,内存:4 GB。在 OSX EL Capitan Ver. 下10.11.6。效果比一项一项功能应用程序差得多。消耗了大约 6GB 的总内存并且从未完成,不得不杀死。从美学上讲,这个解决方案看起来很棒,对我来说最易读。我认为这种退化是由于字典和系列对象需要额外的内存分配。
    • @zork 很高兴知道。这些是您需要的实际功能吗?如果是,我们可以轻松地将其矢量化。
    • 更新了一些有用的信息
    【解决方案3】:

    如果不想创建新函数,可以使用下面的单行:

    >>> df2 = df1.apply(lambda r: pd.Series({'val1': f1(r.a, r.b), 'val2': f2(r.c, r.d)}), axis=1)
    >>> df2
       val1  val2
    0     5    10
    1     5    10
    2     5    10
    3     5    10
    

    【讨论】:

      猜你喜欢
      • 2019-11-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-10-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多