如何使用groupby()函数进行数据切片?机器学习项目中分组数据特征提取的问题咨询
嘿,我来帮你搞定这个问题!首先得搞清楚你为啥会遇到那个报错——SeriesGroupBy对象是分组后的集合,它本身没有iloc属性,iloc是给单个Series/DataFrame用的索引方法。你得对每个分组单独做操作,这时候apply方法就派上用场啦。
先理清楚你的需求:每个alphabet+subject组有1000个采样点,要压缩成50个均值点。我分两种情况给你解决方案:
一、固定分块取均值(非滑动,1000→50刚好分20个点一块)
如果是把1000个点分成连续的50块,每块20个点取均值,这样代码写起来很简洁:
import pandas as pd import numpy as np def compress_to_50(group): # 把组内的1000个值转成numpy数组,重塑为50行20列,然后每行取均值 return group.values.reshape(-1, 20).mean(axis=1) # 对每个分组应用压缩函数 compressed_data = new_dataset.groupby(['alphabet', 'subject'])['maccs'].apply(compress_to_50) # 把结果展开成规整的DataFrame(每个均值对应一行) final_dataset = compressed_data.explode().reset_index(name='maccs_mean')
这段代码里,apply(compress_to_50)会遍历每个分组,把每个组的maccs Series传给函数。函数里用reshape(-1,20)自动把1000个值分成50个20点的块,再对每个块求均值,刚好得到50个值。最后用explode把每个组的50个均值拆成单独的行,再重置索引就得到你要的数据集啦。
二、滑动窗口取均值(匹配你原来循环的逻辑)
看你原来的循环是从211到890步长20,窗口是i-10:i+20(也就是窗口大小30),如果是想要滑动窗口的均值,那可以这样写:
def sliding_window_mean(group): window_size = 30 step = 20 # 生成所有窗口的起始索引,确保窗口不超出组的长度 start_indices = np.arange(0, len(group) - window_size + 1, step) # 遍历每个起始点,取窗口内的值计算均值 means = [group.iloc[start:start+window_size].mean() for start in start_indices] return pd.Series(means) # 应用到每个分组 compressed_sliding = new_dataset.groupby(['alphabet', 'subject'])['maccs'].apply(sliding_window_mean) final_sliding_dataset = compressed_sliding.explode().reset_index(name='maccs_sliding_mean')
这里每个组内部是一个普通的Series,所以可以正常用iloc来截取窗口范围啦。
为啥原来的代码会报错?
你原来的写法是直接在SeriesGroupBy对象上用iloc,但这个对象是多个分组的集合,不是单个Series,所以它没有iloc属性。必须通过apply把操作下沉到每个分组内部,每个分组单独处理才行。
内容的提问来源于stack exchange,提问作者Ayşe Hotaman




