Python 解决TypeError: ("'Series' object is not callable", 'occurred at index 13012')

首先,源数据前五行是这样的。

DealTimebf_StudentIDAccNamePerSexMonDealavgMonDealtransaction_timesmonth
02018-07-0113983裘某某-3.7-3.7012018-07-01
12018-07-0114018虞某某-9.5-9.5012018-07-01
22018-07-0114073刘某某-8.0-8.0012018-07-01
32018-07-0114074周某某-14.3-7.1522018-07-01
42018-07-0114097毛某某-10.0-10.0012018-07-01
# 承接上一章,将用户消费数据进行数据透视。

pivoted_counts=df.pivot_table(index="bf_StudentID",columns="month",values="transaction_times",aggfunc="sum").fillna(0)
columns_month=df.month.sort_values().astype("str").unique()
pivoted_counts.columns=columns_month
pivoted_counts.head()
2018-07-012018-08-012018-09-012018-10-012018-11-012018-12-012019-01-01
bf_StudentID
130120.00.010.010.015.07.09.0
1356417.025.082.063.069.075.050.0
135998.010.039.033.034.031.026.0
136858.012.028.033.034.039.017.0
139479.022.081.064.066.072.063.0
# 用applymap+lambda转换数据,只要当月消费超过30次,记为1,反之为0。
pivoted_purchase = pivoted_counts.applymap(lambda x: 1 if x > 30 else 0)
pivoted_purchase.head()
2018-07-012018-08-012018-09-012018-10-012018-11-012018-12-012019-01-01
bf_StudentID
130120000000
135640011111
135990011110
136850001110
139470011111

然后,先 def 定义函数 再apply函数到dataframe。

# 本次学生消费案例:

# 接下来进行用户分层,我们按照学生的消费行为,简单划分成几个维度:新生(新用户)、超爱饭堂的学生(活跃用户)、不爱饭堂的学生(不活跃用户)、偶尔爱饭堂的学生(回流用户)。
# 新生的定义是第一次消费超过30次。超爱饭堂的学生即常客/老客,在某一个时间窗口内有过消费30次以上。不爱饭堂的学生则是时间窗口内没有消费超过30次的老客。回流用户是在上一个窗口中没有消费30次以上,而在当前时间窗口内有过消费30次以上。以上的时间窗口都是按月统计。

# 比如某学生在9月第一次消费30次以上,那么他在9月的分层就是新生(新用户);
# 他在10月消费30次以上,则是超爱饭堂的学生(活跃用户);
# 11月没有消费30次以上,此时是不爱饭堂的学生(不活跃用户);
# 12月再次消费30次以上,此时是偶尔爱饭堂的学生(回流用户);
# 1月还是消费30次以上,是超爱饭堂的学生(活跃用户)。

# 分层会涉及到比较复杂的逻辑判断。

定义函数

def active_status(data):
    status=[]
    for i in range(7):
        
        # 若本月没有“消费30次以上”
        if data[i] == 0:
            if len(status) > 0:
                if status[i-1] == "unreg":
                    status.append("unreg")
                else:
                    status.append("unlike_canteen")
            else:
                status.append("unreg")
        # 若本月“消费30次以上”
        else:
            if len(status) == 0:
                status.append("new")
            else:
                if status[i-1] == "unlike_canteen":
                    status.append("occasionally_like_canteen")
                elif status[i-1] == "unreg":
                    status.append("new")
                else:
                    status.append("love_canteen")
    return status
                
# 函数写得比较复杂,主要分为两部分的判断,以本月是否“消费30次以上”为界。
# 本月没有“消费30次以上”,还要额外判断他是不是新生(新客),
# 因为部分学生是9月份才“消费30次以上”成为新生(新客),那么在7、8月份他应该连新生(新客)都不是,用unreg表示。
# 如果是老客(即前一个月消费30次以上),则为unlike_canteen。

# 本月若有“月消费30次以上”,需要判断是不是第一次“月消费30次以上”,上一个时间窗口有没有“月消费30次以上”。
# 大家可以多调试几次理顺里面的逻辑关系,对用户进行分层,逻辑确实不会简单,而且这里只是简化版本的。

然后使用apply函数,首次运行报错。如下。
("‘Series’ object is not callable", ‘occurred at index 13012’)

# pivoted_purchase_status = pivoted_purchase.apply(lambda x: active_status(x),axis = 1)
# pivoted_purchase_status.head()

#  运行报错:("'Series' object is not callable", 'occurred at index 13012')

纠错过程。如下。

# 那查看一下“index 13012”是何方神圣。
pivoted_purchase.loc[13012]
2018-07-01    0
2018-08-01    0
2018-09-01    0
2018-10-01    0
2018-11-01    0
2018-12-01    0
2019-01-01    0
Name: 13012, dtype: int64
# 看看其他行与索引13012有没有什么区别
pivoted_purchase.loc[13564]

# 没差别。。。
2018-07-01    0
2018-08-01    0
2018-09-01    1
2018-10-01    1
2018-11-01    1
2018-12-01    1
2019-01-01    1
Name: 13564, dtype: int64
pivoted_purchase.shape

# 1730行(学生学号),7列(月份)
(1730, 7)
pivoted_purchase.dtypes
2018-07-01    int64
2018-08-01    int64
2018-09-01    int64
2018-10-01    int64
2018-11-01    int64
2018-12-01    int64
2019-01-01    int64
dtype: object

搜索series和apply函数关系无果后,回到报错提示详情去看,发现了一些线索。(下面的字那么大我也不想的,这编辑器有毒。。。)

看下述报错详情,首先提示错误在(x);

接下来提示错误在active_status(data)的第六行:

----> 6 if data(i) < 30:

缩小到行了,再一细看,果然发现了一个小括号data(i)。

而根据多出查询说明,报错"‘XXX’ object is not callable"一般是因为该用中括号的地方用了小括号。

回到原参考帖去看,果然人家是中括号啊~~~字太小了看不清,认错敲错了。。。

# 这么看来,前面报错(pivoted_purchase.shape)是因为,series不能用于apply函数?
# 搜索无果。

# 回到报错提示去看详情,终于发现了点东东。

# 先看详情:

# <ipython-input-31-17b35956730f> in <lambda>(x)
# ----> 1 pivoted_purchase_status = pivoted_purchase.apply(lambda x: active_status(x),axis = 1)
#       2 pivoted_purchase_status.head()
#       3 
#       4 #  运行报错:("'Series' object is not callable", 'occurred at index 13012')

# <ipython-input-28-331c5573a3a9> in active_status(data)
#       4 
#       5         # 若本月没有“消费30次以上”
# ----> 6         if data(i) < 30:
#       7             if len(status) > 0:
#       8                 if status[i-1] == "unreg":

# TypeError: ("'Series' object is not callable", 'occurred at index 13012')

# -------------------------------------------------------

下面,不是"‘Series’ object is not callable"这个问题了,倒是另一个手误输错数字,或者说逻辑一时混乱输错数字,的纠错过程。一并留下,供参考。

其实有个疑问,如果有高手看到还望解答一二,十分感谢。
就是,每次apply函数作用于原dataframe后,会生成一个新的对象(如下表)。但是又不像表,不能进行一些常见的操作。

搜索了一圈大神帖子,首先市面上相关帖子还比较少,然后根据其中一些解决方案依葫芦画瓢,“将对象转成dataframe”,但是转了之后,原对象中括号里的所有内容(含各个逗号和各个apply结果)都混到了一列中,而且没有列名。。。
总而言之就是没成功转成dataframe。。

pivoted_purchase_status = pivoted_purchase.apply(lambda x: active_status(x),axis = 1)
pivoted_purchase_status.head(8)

# 一开始虽然没运行报错,不过又转化成坑爹的不知道是啥的格式了。
# 而且貌似逻辑不对。显示结果居然全是学生饭堂深度爱好者(love_canteen),这不科学。

# 然后又细细查看,原来是把for i in range(7)后面的if data[i]==0 的“0”误写成“30”了。
# 将if data[i]==30更正回if data[i]==0之后,逻辑正常,如下所示。只是格式问题还需搜索方法来处理。
bf_StudentID
13012    [unreg, unreg, unreg, unreg, unreg, unreg, unreg]
13564    [unreg, unreg, new, love_canteen, love_canteen...
13599    [unreg, unreg, new, love_canteen, love_canteen...
13685    [unreg, unreg, unreg, new, love_canteen, love_...
13947    [unreg, unreg, new, love_canteen, love_canteen...
13948    [unreg, unreg, new, love_canteen, love_canteen...
13949    [unreg, unreg, new, love_canteen, love_canteen...
13950    [unreg, unreg, new, love_canteen, love_canteen...
dtype: object

pivoted_purchase_status.columns
out:
**# AttributeError: ‘Series’ object has no attribute ‘columns’

原来是series格式。

那如何转成dataframe呢?**

网上找了一圈,找到了pd.DataFrame这个法子,试试。

pivoted_purchase_status=pd.DataFrame(pivoted_purchase_status)
pivoted_purchase_status.head()

out:
(长这样,只有两列,一列学号,另一列是中括号里面的所有内容)
bf_StudentID
13012 [unreg, unreg, unreg, unreg, unreg, unreg, unreg]
13564 [unreg, unreg, new, love_canteen, love_canteen…
13599 [unreg, unreg, new, love_canteen, love_canteen…
13685 [unreg, unreg, unreg, new, love_canteen, love_…
13947 [unreg, unreg, new, love_canteen, love_canteen…

pivoted_purchase_status.columns
out:RangeIndex(start=0, stop=1, step=1)

稀奇古怪的RangeIndex,是啥。。。能否分列?Excel好办,不过Python…应该更简单吧。。

问题是,没有列名,何来分列。。。

仍然试试,使用索引2来表示第二列[2]。

month=pivoted_purchase_status[2].str.split(’,’,expand=True)
month.columns=[‘201807’,‘201808’,‘201809’,‘201810’,‘201811’,‘201812’,‘201901’]
pivoted_purchase_status=pivoted_purchase_status.join(month)
pivoted_purchase_status.head()

运行报错:KeyError: 2


这个问题其实后来解决了一丢丢,把格式搞正确成dataframe了,详见另一篇博客:
https://blog.csdn.net/weixin_44216391/article/details/89329804

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值