我正在使用 Python 进行数据分析,并且我在第 1 章的部分内容上遇到了问题。 9(数据聚合和分组操作)“使用函数分组”部分。
具体来说,如果我使用 GroupBy 对象方法或 Numpy 定义的函数,一切都会正常工作。特别是,它忽略带有字符串的列,并且仅对(适当的)数字列进行操作。但是,如果我尝试定义自己的函数来计算一些数字输出,它不会忽略带有字符串的列,并且会返回属性错误。
这是我遇到问题的示例:
df = DataFrame({'data1':np.random.randn(5),
'data2':np.random.randn(5),
'key1':['a','a','b','b','a'],
'key2':['one','two','one','two','one']})
如果我输入其中任何一个,它都可以正常工作(我已将 numpy 导入为 np):
df.groupby('key1').mean()
或
grouped = df.groupby('key1')
grouped.agg(np.mean())
但是如果我尝试这些,我会收到错误(“peak_to_peak”来自书中):
def peak_to_peak(arr):
return arr.max() - arr.min()
grouped.agg(peak_to_peak)
grouped.agg(lambda x: np.mean(x))
尝试“peak_to_peak”给了我一个又大又长的错误,其结尾为:
TypeError: unsupported operand type(s) for -: 'str' and 'str'
尝试使用 np.mean() 的 lambda 函数给我一个很大的长错误,其结尾为:
TypeError: Could not convert onetwoone to numeric
尝试其他用户定义的函数会产生类似的错误。在所有这些情况下,很明显尝试将peak_to_peak()或np.mean()(或其他)应用于df中的“key2”列(的子集),而对于内置方法和预定义函数,它(正确地)忽略“key2”列子集。
任何见解将不胜感激。
更新:事实证明,如果我将“peak_to_peak”或 lambda 函数作为列表传递(例如,grouped.agg([peak_to_peak])),它工作得很好。请注意,这不是本书中的呈现方式,预定义函数也不需要列表。所以,它仍然令人困惑,但至少它是有用的,我想。
在您使用的方法中,您将列作为参数传递给函数,一一传递所有值。但是,由于 key2 列中存在非数字值,因此两个字符串之间无法进行减法。
您可以按照以下方式解决您的问题:
grouped[["data1", "data2"]].agg(peak_to_peak)
grouped[["data1", "data2"]].agg(lambda x: np.mean(x))`