如何将数据集中的字符串列转换为 int?

How can I convert columns of string in dataset to int?

数据集中的一些数据是字符串格式,我应该将它们全部映射到数字形式。我想将数据集中某些列中的字符串数据转换为 int int,以便在 knn 方法中可用。我写了这段代码,但它有这个错误。我该如何解决? 感谢您的考虑。

这是数据集: http://gitlab.rahnemacollege.com/rahnemacollege/tuning-registration-JusticeInWork/raw/master/dataset.csv

此错误出现在这部分代码中:

     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 pd
import numpy as np
import matplotlib.pyplot as plt
from google.colab import files
!pip install sklearn
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.neighbors import KNeighborsClassifier
from 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])

这是因为您在数据集中的第 12 列 (TargetProId) 具有 NaN 值(它是数据框中的空值)。 所以你需要用其他字符串替换它。 例如,您可以将 na 值替换为“Unknown”。

df["TargetProId"]=df["TargetProId"].fillna("Unknown")

NaN 值来自原始 csv 文件中的空字符串。要将它们保留为空字符串,您可以使用 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')

# optional: convert nan to some int value (here: 0)
df2[id_cols] = df2[id_cols].fillna(0)

结果

>>> df2['TargetProId'].head()
0    1181130851071200850681170691090660551030720870...
1    8911811810612110611210908812010605205108207407...
2                                                    0
3                                                    0
4                                                    0
Name: TargetProId, dtype: object

(注意:dtype 仍然是 object 因为 int 值溢出 int64,而是 Python 的任意精度 int 对象;df2.applymap(type).value_counts()显示所有 'id' 列都是 <class 'int'>).

原建议

最初我对 string_to_int() 有另一个建议。它使用默认值显式处理非 str 值。它还使用 struct.unpack() 作为更高性能解码的基础,尽管在这种特定情况下,我怀疑它有多大区别。

import struct

def 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 default

df2 = df.copy()
df2[id_cols] = df2[id_cols].applymap(string_to_int2)