You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

调用lace包cliff函数遇TypeError:map对象不可下标问题

问题分析

错误TypeError: 'map' object is not subscriptable的核心原因是Python3中map()返回的是迭代器而非列表:迭代器不支持下标访问(如[x]语法),且只能被遍历一次。你之前尝试转list但未覆盖所有关键位置,导致错误仍存在。结合代码,主要问题点包括:

  • 迭代器被消耗后无法复用:比如cliff函数中alldata是map迭代器,传入cliff_core后,zip(*data)会遍历消耗掉data,后续代码无法再获取数据。
  • 迭代器不支持下标操作:比如zip(*data)[-1]中,zip(*data)返回的是zip迭代器,无法用[-1]取最后一列;map对象本身也不能下标访问。
  • random.shuffle不支持迭代器:filter()返回的是迭代器,而random.shuffle()要求传入可变序列(如列表)。
修复后的完整代码

1. power函数(同步修正原代码缩进问题)

import copy

def power(L, C, Erange):
    assert len(L) == len(C), "The L and C must be corresponded to each other"
    E = copy.deepcopy(Erange)
    E[0] -= 1
    power_table = dict()
    for c in set(C):  # 遍历每个类别
        first = [index for index, eachc in enumerate(C) if eachc == c]
        rest = [index for index, eachc in enumerate(C) if eachc != c]
        p_first = len(first) / len(L)
        p_rest = len(rest) / len(L)

        powerc = []
        for u, v in zip(E[0:-1], E[1:]):  # 检查区间(u,v]
            like_first = sum([1 for i in first if u < L[i] <= v]) / len(first) * p_first
            like_rest = sum([1 for i in rest if u < L[i] <= v]) / len(rest) * p_rest
            try:
                powerc.append((like_first ** 2 / (like_first + like_rest)))
            except ZeroDivisionError:
                powerc.append(0)

        power_table[c] = powerc

    power_list = []
    for l, c in zip(L, C):
        for e_cursor in range(len(E)):
            if E[e_cursor] >= l:
                break
        power_list.append(round(power_table[c][e_cursor - 1], 2))
    return power_list

2. cliff_core函数

import logging
import random

def cliff_core(data, percentage, obj_as_binary, handled_obj=False):
    # 先将data转成列表,避免迭代器被一次性消耗
    data = list(data)
    if len(data) < 50:
        logging.debug("no enough data to cliff. return the whole dataset")
        return list(range(len(data)))

    # 转置数据并取最后一列,先转成列表再操作(避免zip迭代器无法下标访问)
    data_transposed = list(zip(*data))
    classes = [toolkit.str2num(item) for item in data_transposed[-1]]

    if not handled_obj:
        if obj_as_binary:
            classes = [1 if i > 0 else 0 for i in classes]
        else:
            classes = toolkit.apply_bin_range(classes)

    data_power = [] 
    for col in data_transposed:
        # 将列数据转成列表,避免迭代器问题
        col = [toolkit.str2num(item) for item in col]
        E = toolkit.binrange(col)
        data_power.append(power(col, classes, E))
    
    # 转置data_power并转成列表
    data_power = list(map(list, zip(*data_power)))
    row_sum = [sum(row) for row in data_power]

    index = list(range(len(data)))
    zips = list(zip(data, classes, row_sum, index))

    output = []
    for cls in set(classes):
        # 将filter结果转成列表,支持shuffle操作
        matched = list(filter(lambda z: z[1] == cls, zips))
        random.shuffle(matched)
        matched = sorted(matched, key=lambda z: z[2], reverse=True)

        if len(matched) < 5:
            output.extend([m[3] for m in matched])  # 保留所有数据
            continue

        for i in range(int(len(matched) * percentage)):
            output.append(matched[i][3])
    return sorted(output)

3. cliff函数

def cliff(attribute_names, data_matrix, independent_attrs, objective_attr, objective_as_binary=False, cliff_percentage=0.4):
    ori_attrs, alldata = attribute_names, data_matrix
    # 转成列表,避免迭代器问题
    alldata_t = list(map(list, zip(*alldata)))
    valued_data_t = []
    for attr, col in zip(ori_attrs, alldata_t):
        if attr in independent_attrs:
            valued_data_t.append(col)
    # 添加目标属性列
    valued_data_t.append(alldata_t[attribute_names.index(objective_attr)])  
    # 转成列表
    alldata = list(map(list, zip(*valued_data_t)))
    # 将所有元素转成数值,嵌套转成列表
    alldata = [list(map(toolkit.str2num, row)) for row in alldata]
    after_cliff = cliff_core(alldata, cliff_percentage, objective_as_binary)
    res = [data_matrix[i] for i in after_cliff]
    return res
关键修复点说明
  • 所有map()结果显式转成列表:比如alldata = list(map(...)),确保数据是可重复访问、支持下标的列表类型。
  • 转置数据时先转成列表:data_transposed = list(zip(*data)),避免zip迭代器无法下标访问的问题,同时保留转置后的所有列数据。
  • filter()结果转成列表:matched = list(filter(...)),让random.shuffle()可以正常修改序列。
  • 嵌套迭代器转列表:alldata = [list(map(...)) for row in alldata],将每行的map迭代器转成列表,确保后续可以正常访问每行元素。

内容的提问来源于stack exchange,提问作者NDaq

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.23 14:54:22