Numpy float object not iterable while running a function

Viewed 60

I am trying to assign name to a cluster basis on the some comparative conditions, however i am getting error stating as numpy float object not iterable. Besides i don't wish to subset the dataset as you can see below from df to df1 and later concat it. Below is the code:

import pandas as pd
df = pd.DataFrame({'cluster':[0, 1, 2, 9999], 'earlypc':[88.943,4.034,6.839,0.488],'C':[3.491,8.306,75.329,34.5],'D':[14.548,87.66,17.832,65.012]})
df1=df[df['cluster']!=999]
def cluster(a,b,c,d):
    if(max(b)==b):
        return 'high'
    elif (max(c)==c):
         return 'low'
    elif (max(d)==d):
        return 'medium'
    else: return 'medium'

df1['Vendor_Segmentation']=df1.apply(lambda x:cluster(x['cluster'],x['earlypc'],x['C'],x['D']),axis=1)

TypeError: 'numpy.float64' object is not iterable
2 Answers

I second the above opinion to not use apply, and provide two alternatives from the numpy package that are designed for cases like yours:

import numpy as np
import pandas as pd
  1. numpy.select
# Specify the conditions
conditions = [ 
    (df1['earlypc'] == df1['earlypc'].max()),
    (df1['C'] == df1['C'].max()),
    (df1['D'] == df1['D'].max())     
    ]

# What each condition should return
choices =['high','low','medium']

# Return the array as a column
df1['Vendor_segmentation'] = np.select(conditions, choices,default='medium')

2 numpy.where

df1['Vendor_segmentation'] = np.where(df1['earlypc'].eq(df1['earlypc'].max()),'high',
                              np.where(df1['C'].eq(df1['C'].max()),'low',
                              np.where(df1['D'].eq(df1['D'].max()),'medium',
                                                                   'medium')))

Print:

Out[531]: 

   cluster  earlypc       C       D Vendor_segmentation
0        0   88.943   3.491  14.548                high
1        1    4.034   8.306  87.660              medium
2        2    6.839  75.329  17.832                 low
3     9999    0.488  34.500  65.012              medium

Series.eq or == are equivalent.

How about not using apply at all:

df1['Vendor_Segmentation'] = 'medium'
df1.loc[df1.earlypc==df1.earlypc.max(), "Vendor_Segmentation"] = 'high'
df1.loc[df1.C==df1.C.max(), "Vendor_Segmentation"] = 'low'
df1.loc[df1.D==df1.D.max(), "Vendor_Segmentation"] = 'medium'

This gives the desired result.

    cluster earlypc C   D        Vendor_Segmentation
0   0       88.943  3.491   14.548      high
1   1       4.034   8.306   87.660      medium
2   2       6.839   75.329  17.832      low
3   9999    0.488   34.500  65.012      medium
Related