【问题标题】:What is the best way to write a function to compute row-wise elements in panda?编写函数来计算熊猫中的逐行元素的最佳方法是什么?
【发布时间】:2018-10-23 08:08:27
【问题描述】:

我有一个像这样的基表:

col1 是一列独立值,col2 是基于 Country 和 Type 组合的聚合。我想使用以下逻辑计算列 col3 到 col5:

  1. col3:col1 中一个元素与col1 总数的比值
  2. col4:col1 中的元素与 col2 中对应元素的比率
  3. col5:col3 和 col4 中逐行元素乘积的自然指数

我写了一个类似下面的函数来实现这个:

def calculate(df):
  for i in range(len(df)):
    df['col3'].loc[i] = df['col1'].loc[i]/sum(df['col1'])
    df['col4'].loc[i] = df['col1'].loc[i]/df['col2'].loc[i]
    df['col5'].loc[i] = np.exp(df['col3'].loc[i]*df['col4'].loc[i])
  return df

这个函数执行了,给了我预期的结果,但是笔记本也抛出了一个警告:

SettingWithCopyWarning:

试图在数据帧的切片副本上设置值

请参阅文档中的注意事项: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy

我不确定我是否在这里编写了最好的函数。任何帮助,将不胜感激!谢谢。

【问题讨论】:

  • 嗯,你应该致力于矢量化而不是使用 for 循环。你如何在这里分享你的数据集和预期的输出——>更容易提供帮助。不错的努力!
  • 以下解决方案之一有帮助吗?随意接受一个(在左侧打勾),或要求澄清。
  • 道歉 - 我是这个平台的新手。是的,它有帮助!非常感谢您的 cmets。

标签: python pandas function dataframe


【解决方案1】:

我认为apply 和 pandas 中的循环最好避免,所以更好更快的是使用 vewctorized 解决方案:

df = pd.DataFrame({'col1':[4,5,4,5,5,4],
                   'col2':[7,8,9,4,2,3],
                   'col3':[1,3,5,7,1,0],
                   'col4':[5,3,6,9,2,4],
                   'col5':[1,4,3,4,0,4]})

print (df)
   col1  col2  col3  col4  col5
0     4     7     1     5     1
1     5     8     3     3     4
2     4     9     5     6     3
3     5     4     7     9     4
4     5     2     1     2     0
5     4     3     0     4     4

df['col3'] = df['col1']/(df['col1']).sum()
df['col4'] = df['col1']/df['col2']
df['col5'] = np.exp(df['col3']*df['col4'])
print (df)
   col1  col2      col3      col4      col5
0     4     7  0.148148  0.571429  1.088343
1     5     8  0.185185  0.625000  1.122705
2     4     9  0.148148  0.444444  1.068060
3     5     4  0.185185  1.250000  1.260466
4     5     2  0.185185  2.500000  1.588774
5     4     3  0.148148  1.333333  1.218391

时间安排

df = pd.DataFrame({'col1':[4,5,4,5,5,4],
                   'col2':[7,8,9,4,2,3],
                   'col3':[1,3,5,7,1,0],
                   'col4':[5,3,6,9,2,4],
                   'col5':[1,4,3,4,0,4]})

#print (df)

#6000 rows
df = pd.concat([df] * 1000, ignore_index=True)

In [211]: %%timeit
     ...: df['col3'] = df['col1']/(df['col1']).sum()
     ...: df['col4'] = df['col1']/df['col2']
     ...: df['col5'] = np.exp(df['col3']*df['col4'])
     ...: 
1.49 ms ± 104 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

不幸的是,这个示例的循环解决方案确实很慢,因此仅在60 rows DataFrame 中进行了测试:

#60 rows
df = pd.concat([df] * 10, ignore_index=True)

In [3]: %%timeit
   ...: (calculate(df))
   ...: 
C:\Anaconda3\lib\site-packages\pandas\core\indexing.py:194: SettingWithCopyWarning: 
A value is trying to be set on a copy of a slice from a DataFrame

See the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy
  self._setitem_with_indexer(indexer, value)
10.2 s ± 410 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

【讨论】:

    【解决方案2】:

    使用pandas 进行矢量化计算。循环计算是可能的,但它们效率低下,因为它们不是用连续的数值数组处理的。

    col3:col1中一个元素占col1总数的比例

    df['col3'] = df['col1'] / df['col1'].sum()
    

    col4:col1中的元素与col2中对应元素的比例

    df['col4'] = df['col1'] / df['col2']
    

    col5:col3 和 col4 中逐行元素的乘积的自然指数

    df['col5'] = np.exp(df['col3'] * df['col4'])
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-12-03
      • 1970-01-01
      • 2016-12-20
      • 2021-10-10
      • 1970-01-01
      • 1970-01-01
      • 2019-12-05
      • 1970-01-01
      相关资源
      最近更新 更多