【特征工程】常用操作

1. 查看表信息

df.info()

df.dtypes  # 查看列的类型

df.columns  # 查看所有列名

df['A'].value_counts()  # 查看某列不同值的数量

df.isnull().sum()  # 查看每列缺失值个数(import numpy)

df['A'].nunique()  # 查看某列有多少个不同的值

df.duplicated().sum()  # 查看表中是否存在重复行(import numpy)

2. one-hot 编码

对 DataFrame 对象进行 one-hot 编码(不包括二分类)

import numpy as np
from sklearn.preprocessing import OneHotEncoder


encoder = OneHotEncoder(drop='if_binary')  # drop='if_binary'代表去除二分类的列

one_hot_encoded_data = encoder.fit_transform(df).toarray()

encoder.categories_  # 查看每列对应的类别

 在 DataFrame 转换成独热编码后保留列名,需要自己写操作,并没有现成的函数:

import numpy as np
from sklearn.preprocessing import OneHotEncoder


encoder = OneHotEncoder(drop='if_binary')  # 创建编码对象

# 提取原始的列名称
col_names = df.columns.tolist()

# 新编码字段名称列表
new_col_names = []

# 提取 one-hot 编码后所有特征的名称
for i, j in enumerate(col_names):
    if len(encoder.categories_[i]) == 2:
        new_col_names.append(i)
    else:
        for f in encoder.categories_[i]:
            feature_name = j + '_' + f
            new_col_names.append(feature_name)

# 组合成新的 DataFrame 
pd.DataFrame(encoder.fit_transform(df).toarray(), columns=new_col_names)

3. 连续值分箱(连续值转换离散值) 

import pandas as pd
import numpy as np

from sklearn.preprocessing import KBinsDiscretizer


df = pd.DataFrame({'A': [0, 10, 180, 50, 30, 55, 99, 80, 75, 10, 300]})

# 特征必须是列向量,不然 KBinsDiscretizer 无法识别
income = np.array(df['A']).reshape(-1, 1)  

# 等宽分箱:分组间隔相同(strategy='uniform')
# dis = KBinsDiscretizer(n_bins=3, encode='ordinal', strategy='uniform')  

# 等频分箱:每组元素个数相同,如果除不尽,余数放最后一组(strategy='quantile')
# dis = KBinsDiscretizer(n_bins=2, encode='ordinal', strategy='quantile')  

# 聚类分箱:通常优先使用(strategy='kmeans')
dis = KBinsDiscretizer(n_bins=3, encode='ordinal', strategy='kmeans') 

dis.fit_transform(income)  # 对特征进行分箱操作

dis.bin_edges_  # 查看分箱的边界

4. 分组统计 + 特征衍生

import pandas as pd

df_0 = pd.DataFrame({'A': [1, 1, 2, 3, 2], 
                     'B': [1, 2, 2, 3, 1], 
                     'C': [29, 31, 64, 95, 11], 
                     'D': [1, 2, 3, 4, 5]})

# 取出 A B C 三列
df = df_0[['A', 'B', 'C']] 

# 以A列分组,其他列按照分组求均值
df.groupby('A').mean()  

# 按照多列分组
df.groupby(['A', 'B'])  

# 对其他列按照分组进行多种计算
df.groupby('A').agg(['min', 'max', 'mean']).reset_index()  

# 对部分列按照分组对不同列进行不同计算
data = df.groupby('A').agg({'B': ['min', 'max', 'mean'], 'C': ['max']}).reset_index()  

# 修改列名称
data.columns = ['A', 'B_A_max', 'B_A_min', 'B_A_mean', 'C_A_max']  

# 以 A 列为主键拼接group_by后的数据和原始数据
df_all = pd.merge(df_0, data, how='left', on='A')  

对于连续型变量的统计可以使用的方法:

  • mean / var:均值、方差
  • max / min :最大值最小值
  • skew:数据分布偏度,小于0时左偏,大于0时右偏

对于分类变量,还有这些连续型变量的统计方法:

  • median:中位数
  • count:个数统计
  • nunique:类别数
  • quantile:分位数

对于分位数,需要通过自定义函数实现:

def q1(x):
    # 计算下四分位数
    return x.quantile(0.25)


def q2(x):
    # 计算上四分位数
    return x.quantile(0.25)


aggs = {'B': [q1, q2]}  # 计算B列的上四分位数、下四分位数

df.groupby('A').agg(aggs).reset_index()

5. 时序特征处理 + 特征衍生

 DataFrame 中的时间列转换为 datetime 类型:

t['time'] = pd.to_datetime(t['time'])  # 将time列转换为datetime类型

调整精度:

t['time'].values  # 将时间列转换为ndArray对象,但是ndArray默认精度为纳秒(ns)

t['time'].values.astype('datetime64[D]')  # 将精度调整为天

t['time_D'] = t['time'].values.astype('datetime64[D]')  # 添加一个时间为天的列

 根据时间特征计算并添加其他特征列:

t['year'] = t['time'].dt.year                       # 年
t['month'] = t['time'].dt.month                     # 月
t['day'] = t['time'].dt.day                         # 日
t['hour'] = t['time'].dt.hour                       # 时
t['minute'] = t['time'].dt.minute                   # 分
t['second'] = t['time'].dt.second                   # 秒

t['quarter'] = t['time'].dt.quarter                 # 季度
t['dayofweek'] = t['time'].dt.dayofweek + 1         # 周几,从0开始,需要+1
t['dayofyear'] = t['time'].dt.dayofyear             # 一年中的第几天

t['hour_section'] = (t['hour'] // 6).astype(int)    # 查看是凌晨、上午、下午、晚上

计算时间差:

# 计算时间差,结果为timedelta类型
t['time'][1] - t['time'][0]                         # 元素相减
t['time'] - pd.Timestamp('2024-01-01 00:00:00')     # 与固定时间相减
t['time_diff'] = t['time_1'] - t['time_2']          # 列相减

# 粗略计算
t['time_diff'].dt.days                               # 天
t['time_diff'].dt.seconds                            # 秒(只在时、分、秒维度计算,不考虑天)
np.round(t['time_diff'].dt.days / 30).astype('int')  # 月

# 精确计算
t['time_diff'].values                                # 返回纳秒计算结果
t['time_diff'].values.astype('timedelta64[h]')       # 时
t['time_diff'].values.astype('timedelta64[s]')       # 秒

# 如果要拼接到表中,需要再转换为int类型
t['time_diff_s'] = t['time_diff'].values.astype('timedelta64[s]').astype(int)

 关键时间点的选取:

import datetime


# 起止时间的选取
t['time'].max()
t['time'].min()

# 获取当前时间,默认获取的时间是毫秒级(ms)
cur_time = datetime.datetime.now()
pd.Timestamp(cur_time)  # 转换为pandas的datetime类型

# 自定义时间输出格式,并借此输出指定精度的时间
pd.Timestamp(cur_time.strftime('%Y-%m-%d %H:%M:%S'))

6. 方差分析(Analysis of Variance, ANOVA)

df.dropna(subset=['A', 'B'])

缺失值处理

df.dropna(subset=['A', 'B'])

其他操作 

保存为csv(不带index)

df.to_csv('/path/filename.csv', index=False)  # 保存csv

df.to_csv('/path/filename.txt', index=False, sep='|')  # 保存txt,并设置分隔符

pandas遍历表时添加进度条:

from tqdm import tqdm

for i in tqdm(df.iteritems(), total=df.shape[0]):
    time.sleep()

pandas将连续值按照范围转换为离散值

# 将年龄按照10为间隔划分
data['age_range'] = pd.cut(data['age'], list(range(0, 101, 10)))

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值