均值归一化不同版本的代码

时间:2015-01-19 04:45:36

标签: python pandas

我想要规范化我的数据框,当我实现第一版代码时,我得到了规范化的值,但是当我实现版本2时,我收到一个名为stop iteration的错误。 ["1B","2B","3B","HR","BB"]是我数据框中的列。

版本1:

def meanNormalizeRates(df):
        subRates = df[["1B","2B","3B","HR","BB"]]
        df[["1B","2B","3B","HR","BB"]] = subRates - subRates.mean(axis=0)
        return df

stats = stats.groupby('yearID').apply(meanNormalizeRates)
stats.head()

版本2:

 def mean(df):
    for val in ["1B","2B","3B","HR","BB"]:
          stats[val] = stats[val] -stats[val].mean(axis=0)

stats = stats.groupby('yearID').apply(mean)

stats.head()

我无法理解两个版本之间的区别。

一个很好的例子

data = {'state': ['Ohio', 'Ohio', 'Ohio', 'Nevada', 'Nevada'],
'year': [2000, 2001, 2002, 2001, 2002],
'pop': [1.5, 1.7, 3.6, 2.4, 2.9],
'gate' : [9, 7, 4,6, 9]}

frame = pd.DataFrame(data)
frame.head()

版本1.1

def std(df):
    temp = df[['gate', 'pop']]
    df[['gate', 'pop']] = temp - temp.mean(axis=0)
    return df
frame.groupby('year').apply(std)

    gate    pop state   year
0   9   1.5 Ohio    2000
1   7   1.7 Ohio    2001
2   4   3.6 Ohio    2002
3   6   2.4 Nevada  2001
4   9   2.9 Nevada  2002

版本1.2

def mean(df):
    for val in ['gate', 'pop']:
        df[val] = df[val]- df[val].mean(axis=0)

frame.groupby('year').apply(mean)

error: stop iteration

1 个答案:

答案 0 :(得分:1)

好的,因为你的mean()函数中没有return语句(在例1.2中),该函数只为每个组返回None。你得到的StopIteration错误并不是那么清楚,但发生的事情是:

  • apply()会在每个群组中调用您的mean()功能。
  • 每次调用都会返回None
  • 结果会被列入一个列表,所以这里列出了所有结果 NoneŠ
  • 作为尝试将结果拼接在一起的一部分, apply()尝试在列表中查找非None值, 引发StopIteration例外。

所以基本上你可以通过这样做来重现错误:

eg_list = [None, None, None]
v = next(v for v in eg_list if v is not None)
---------------------------------------------------------------------------
StopIteration                             Traceback (most recent call last)
<ipython-input-12-93b31b7a51e4> in <module>()
----> 1 v = next(v for v in eg_list if v is not None)

所有这些可能都是太详细了 - 外卖的是你什么时候 使用apply(),您不应该真正在进行所有更改 你应用的功能 - 你应该从函数返回一个结果 并将它们分配回数据框,如:

# The lambda here will return the relevant values of gate and pop,
# and we just assign them wherever we want in the dataframe.
# Could be new columns, could be existing ones
frame[['gate', 'pop']] = frame.groupby('year')[['gate', 'pop']].apply(
    lambda group: group - group.mean(axis=0))