【问题标题】:scaling only numeric values in data frame that contain string仅缩放包含字符串的数据框中的数值
【发布时间】:2020-04-01 02:42:09
【问题描述】:

我在 python 中,我正在尝试缩放到数据框

subject_id hour_measure         urinecolor   blood pressure                  
3          1.00                 red          40
           1.15                 red          high
4          2.00              yellow          low

因为它包含数字和文本列 以下代码给了我错误

 #MinMaxScaler for Data
scaler = MinMaxScaler(copy=True, feature_range=(0, 1))
X = scaler.fit_transform(X)

它给了我错误,因为数据框包含字符串,我如何告诉 python 只缩放包含数字的列,并缩放字符串列中的数值。

【问题讨论】:

  • 您想缩放混合列中的数字 - 例如“血压”还是仅在数字列中?如果它只是数字列,您可以只对这些列进行子集化,例如X[['hour_meassure',...]] = scaler.fit_transform(['hour_meassure',...])
  • 我想缩放所有数字列,以及字符串列中的数值(例如附件示例中的血压)
  • 是否也发送了电子邮件?

标签: python python-3.x pandas scikit-learn


【解决方案1】:

将非数值转换为缺失值,然后使用alternative solution进行缩放,最后将缺失值替换回原来的值:

print (df)
   subject_id  hour_measure urinecolor blood pressure
0           3          1.00        red             40
1           3          1.15        red           high
2           4          2.00     yellow            low
3           5          5.00     yellow            100

df = df.set_index('subject_id')

df1 = df.apply(lambda x: pd.to_numeric(x, errors='coerce'))
df2 = (df1 - df1.min()) / (df1.max() - df1.min())

df = df2.combine_first(df)
print (df)
            hour_measure urinecolor blood pressure
subject_id                                        
3                 0.0000        red              0
3                 0.0375        red           high
4                 0.2500     yellow            low
5                 1.0000     yellow              1

第一个解决方案

我建议通过字典将文本列替换为数字,例如:

dbp = {'high': 150, 'low': 60}

df['blood pressure'] = df['blood pressure'].replace(dbp)

大家一起:

#if subject_id are numeric convert them to index
df = df.set_index('subject_id')

dbp = {'high': 150, 'low': 60}
#replace to numbers and convert to integers
df['blood pressure'] = df['blood pressure'].replace(dbp).astype(int)

print (df)
            hour_measure urinecolor  blood pressure
subject_id                                         
3                   1.00        red              40
3                   1.15        red             150
4                   2.00     yellow              60

print (df.dtypes)
hour_measure      float64
urinecolor         object
blood pressure      int32
dtype: object

from sklearn import preprocessing

scaler = preprocessing.MinMaxScaler(copy=True, feature_range=(0, 1))
#select only numeric columns
X = scaler.fit_transform(df.select_dtypes(np.number))
print (X)
[[0.         0.        ]
 [0.15       1.        ]
 [1.         0.18181818]]

详情

print (df.select_dtypes(np.number))
            hour_measure  blood pressure
subject_id                              
3                   1.00              40
3                   1.15             150
4                   2.00              60

【讨论】:

  • 感谢您的关心和时间。但没有解决方案只缩放字符串列中的数值
  • @Nora - 可能,但解决方案已完全改变。
  • 如果您不介意将先前的解决方案也添加到测试这两个解决方案的答案中
  • 在您手动缩放的解决方案中,我不想缩放 hour_measure 列,如何将其从缩放中移除
  • @Nora 用于在 0 and 52 之间进行缩放,使用 min1 = 0 max1 = 52 df2 = (df1 - df1.min()) / (df1.max() - df1.min()) df2 = df2 * (max1 - min1) + min1
【解决方案2】:

另一种方法如下:(我添加了新行,参见血压的比例值)

       hour_measure urinecolor blood pressure  temp_column
0          1.00        red             40           40
1          1.15        red           high            0
2          2.00     yellow            low            0
3          3.00     yellow             20           20

df['temp_column'] = df['blood pressure'].values
df['temp_column'] = df['temp_column'].apply(lambda x: 0 if str(x).isalpha() == True else x)

这将使用血压列的数值创建一个新的 temp_column。

scaler = MinMaxScaler(copy=True, feature_range=(0, 1))
df['hour_measure'] = scaler.fit_transform(df['hour_measure'].values.reshape(-1, 1))
df['temp_column'] = scaler.fit_transform(df['temp_column'].values.reshape(-1 ,1))

我已将 MinMaxScaler 应用于包含血压数值的 temp_column。我只是将缩放后的数值放回血压列中。

numeric_rows = pd.to_numeric(df['blood pressure'], errors='coerce').dropna().index.tolist()
print('Index of numeric values in blood pressure column: ', numeric_rows)
for i in numeric_rows:
    df['blood pressure'].iloc[i] = df['temp_column'].iloc[i]
df = df.drop(['temp_column'], axis=1)

结果:

   hour_measure urinecolor blood pressure
0         0.000        red              1
1         0.075        red           high
2         0.500     yellow            low
3         1.000     yellow            0.5

【讨论】:

    猜你喜欢
    • 2021-10-13
    • 1970-01-01
    • 2020-12-13
    • 1970-01-01
    • 2016-10-19
    • 2018-12-18
    • 1970-01-01
    • 2022-01-22
    • 2021-01-11
    相关资源
    最近更新 更多