数据集中部分数据以字符串格式存在,我需要将它们全部映射到数值形式。我希望将数据集中某些列的字符串数据转换为整数,以便在knn方法中使用。我编写了这段代码,但出现了错误。如何修复它?感谢您的考虑。
错误出现在代码的这一部分:
def string_to_int(s): ord3 = lambda x : '%.3d' % ord(x) return int(''.join(map(ord3, s))) for i in range(1,24857): df.iloc[i,0]=string_to_int(df.iloc[i,0]) df.iloc[i,1]=string_to_int(df.iloc[i,1]) df.iloc[i,3]=string_to_int(df.iloc[i,3]) df.iloc[i,8]=string_to_int(df.iloc[i,8]) df.iloc[i,9]=string_to_int(df.iloc[i,9]) df.iloc[i,10]=string_to_int(df.iloc[i,10]) df.iloc[i,11]=string_to_int(df.iloc[i,11]) df.iloc[i,12]=string_to_int(df.iloc[i,12])
错误信息如下:
TypeError Traceback (most recent call last)<ipython-input-7-f5bce11c577a> in <module>() 30 df.iloc[i,10]=string_to_int(df.iloc[i,10]) 31 df.iloc[i,11]=string_to_int(df.iloc[i,11])---> 32 df.iloc[i,12]=string_to_int(df.iloc[i,12]) 33 34 <ipython-input-7-f5bce11c577a> in string_to_int(s) 20 def string_to_int(s): 21 ord3 = lambda x : '%.3d' % ord(x) ---> 22 return int(''.join(map(ord3, s))) 23 24 for i in range(1, 24857):TypeError: 'float' object is not iterable
完整代码如下:
import pandas as pdimport numpy as npimport matplotlib.pyplot as pltfrom google.colab import files!pip install sklearnfrom sklearn.model_selection import train_test_splitfrom sklearn.preprocessing import StandardScalerfrom sklearn.neighbors import KNeighborsClassifierfrom sklearn.metrics import classification_report, confusion_matrix#-----------------read file-------------------uploaded = files.upload()with open('dataset.csv', 'r') as data: df3 = pd.read_csv(data , encoding = ('ansi')) lst = ['id', 'Prold', 'ProCreationId', 'CustCreatonRate', 'TaskCreationTimestamp', 'Price', 'ServiceId', 'CategoryId', 'ZoneId', 'TaskState', 'TargetProId', 'isFraud'] df = pd.DataFrame(df3) print (df)#----------------------preprocessing----------------def string_to_int(s): ord3 = lambda x : '%.3d' % ord(x) return int(''.join(map(ord3, s)))for i in range(1,24857): df.iloc[i,0]=string_to_int(df.iloc[i,0]) df.iloc[i,1]=string_to_int(df.iloc[i,1]) df.iloc[i,3]=string_to_int(df.iloc[i,3]) df.iloc[i,8]=string_to_int(df.iloc[i,8]) df.iloc[i,9]=string_to_int(df.iloc[i,9]) df.iloc[i,10]=string_to_int(df.iloc[i,10]) df.iloc[i,11]=string_to_int(df.iloc[i,11]) df.iloc[i,12]=string_to_int(df.iloc[i,12])
回答:
原始csv文件中的空字符串导致了NaN
值。为了保留这些空字符串,您可以使用df = pd.read_csv(url, keep_default_na=False)
读取csv文件,尽管将它们作为NaN
处理会更方便一些。
然而,正如评论中所指出的,我对该数据所使用的编码标准(如果有的话)的正确解释持怀疑态度。
但如果数据如问题中描述的那样,那么您可以不更改地使用您的string_to_int
函数,将其应用于所有'...Id'
列,并跳过NaN
值(可选择性地将这些值转换为其他值):
id_cols = [k for k in df.columns if k.lower().endswith('id')]df2 = df.copy()df2[id_cols] = df2[id_cols].applymap(string_to_int, na_action='ignore')# 可选:将nan值转换为某个整数值(此处为0)df2[id_cols] = df2[id_cols].fillna(0)
结果
>>> df2['TargetProId'].head()0 1181130851071200850681170691090660551030720870...1 8911811810612110611210908812010605205108207407...2 03 04 0Name: TargetProId, dtype: object
(注意:数据类型仍然是object
,因为整数值超出了int64
的范围,而是Python的任意精度整数对象;df2.applymap(type).value_counts()
显示所有'id'
列都是<class 'int'>
)。
原始建议
最初我对string_to_int()
提出了另一个建议。它明确处理非字符串值,并设置默认值。它还使用struct.unpack()
作为更高效解码的基础,尽管在这种特定情况下,我怀疑这不会有太大区别。
import structdef string_to_int2(s, default=0): if isinstance(s, str): n = len(s) b = s.encode('ascii') return int(''.join([f'{v:03d}' for v in struct.unpack(f'{n}B', b)])) return defaultdf2 = df.copy()df2[id_cols] = df2[id_cols].applymap(string_to_int2)