数据分析2 - 数据导入及处理

数据存在的形式

  • 文件:csv, excel, txt……
  • 数据库:mysql, access, sql server……
  • 导入 CSV 文件

    pandas 包中的 read_csv 函数: read_csv(file, encoding)

    pandas.read_csv参数整理

    from pandas import read_csv
    # 相对地址
    df = read_csv(
                r'1.csv'
    df = read_csv(
                './1.csv'
    # 绝对地址
    df = read_csv(
                r'C:\Users\lian\Desktop\python\4.1\1.csv'
    df = read_csv(
                'C:/Users/lian/Desktop/python/4.1/1.csv'
    

    导入文本文件

    pandas 包中的 read_table 函数:read_table(file,names=[列名1,列名2,...],sep="",encoding,...)

    dataFrame.duplicated() 找出或只按指定列找出重复的行,根据是否重复返回元素值为 boolean 的 Series,表示是否重复(重复为 True) dataFrame.drop_duplicates() 删除或值考虑某一列的值删除重复的行,返回新的 DataFrame
    from pandas import read_csv
    # 导入数据
    df = read_csv('data.csv')
    # 找出行重复的位置。返回一个 Series,值为 boolean ,表示每行是否重复,当行所有元素的值都重复时,返回 True
    dIndex = df.duplicated()
    # 根据某些列,找出重复的位置
    dIndex = df.duplicated('id')
    # 当指定多列时,是 and 关系,即所有指定列都重复了才为 True
    dIndex = df.duplicated(['id', 'key'])
    #根据返回值,把重复数据提取出来
    df[dIndex]
    #直接删除重复值
    #默认根据所有的列,进行删除
    newDF = df.drop_duplicates()
    #当然也可以指定某一列,进行重复值处理
    newDF = df.drop_duplicates('id')
    

    缺失值的处理

    缺失值的处理方式:1. 数据补齐;2. 删除对应缺失行;3. 不处理

    相关函数:

  • dataFrame.isnull()
  • dataFrame.any(axis=1)
  • dataFrame.fillna('填充 nan 的值')
  • dataFrame.dropna()
  • from pandas import read_csv
    # 导出数据
    # data.csv 本身已有缺失值
    df = read_csv(
        'data.csv'
    # data2.csv 无缺失值,na_values=['a','b'] 表示将元素值为 a 或 b 的元素值设置为 nan
    df = read_csv(
        'data2.csv',
        na_values=['a','b']
    # 找出空值的位置
    # isnull() 函数返回一个同结构的 DataFrame(大小、列名、索引相同),但元素值以是否为 null ( nan ) 设置为 boolean 值
    isNA = df.isnull()
    # 获取出空值所在的行
    # isNA.any(axis=1) 返回一个 boolean 值的 Series ,当 axis=1 时表示 isNA 的每一行是否有存在值为 True 的元素,只要有则对应的 boolean 为 True 
    # 再根据 dataFrame[series] 过滤出有空值的行
    df[isNA.any(axis=1)]
    # 获取根据某一列或多列中存在空值所在的行
    # isNA[['key']] 得到的是 DataFrame,isNA['key'] 得到的是 Series
    df[isNA[['key']].any(axis=1)]
    # 获取 key 或 value 列中空值所在的行
    df[isNA[['key', 'value']].any(axis=1)]
    # 将 df 中元素值为 nan 的值设置为 '未知'
    df.fillna('未知')
    # 直接删除空值。将有空值的该行删除
    newDF = df.dropna()
    

    空格值的处理

    相关函数:

    str.strip() 清除字符型数据左右的空格(lstrip() 清除左边,rstrip() 清除右边) series.str.xxx 表示对 series 中所有字符元素做处理
    from pandas import read_csv
    df = read_csv(
        'data.csv'
    # 处理 name 字段中元素的字符
    newName = df['name'].str.lstrip()
    newName = df['name'].str.rstrip()
    newName = df['name'].str.strip()
    df['name'] = newName
    

    字段抽取是根据指定字段下的一组数据的开始和结束位置,抽取形成新的列

    相关函数:

    series.astype(str) 对 series 中所有元素转化为 str 类型 str.slice(0, 3) 对 str 做切片

    字段截取函数:slice(start, stop)

    from pandas import read_csv
    df = read_csv(
        'data.csv'
    # 将 df 数据框中 tel 字段的元素值的类型转化为 str 类型,并赋值回去
    df['tel'] = df['tel'].astype(str)
    bands = df['tel'].str.slice(0, 3)
    areas = df['tel'].str.slice(3, 7)
    nums = df['tel'].str.slice(7, 11)
    #赋值回去
    df['bands'] = bands
    df['areas'] = areas
    df['nums'] = nums
    

    字段拆分指按照固定的字符,拆分已有字符串

    相关函数:

  • str.split(sep, n, expand)
  • 记录抽取指根据一定的条件,对数据进行抽取

    相关函数:
    dataFrame[condition] condition 为一 Series,元素数量与 dataFrame 行数相等,元素为 boolean 值,决定是否抽取记录

    常用的条件类型:

    > < >= <= != between(left, right) pandas.isnull(column) str.contains(pattern, na=False) & | not
    df[(df.comments >= 1000) & (df.comments <= 10000)] 等价于 df[df.comments.between(1000, 10000)]
    import pandas
    df = pandas.read_csv(
        'data.csv', sep="|"
    df[df.comments>10000]
    df[df.comments.between(1000, 10000)]
    #过滤空值所在行
    df[pandas.isnull(df.title)]
    #根据关键字过滤
    df[df.title.str.contains('台电', na=False)]
    #~为取反
    df[~df.title.str.contains('台电', na=False)]
    #组合逻辑条件
    df[(df.comments>=1000) & (df.comments<=10000)]
    

    随机抽样指随机从数据中,按照一定的函数或者比例抽取数据

    相关函数:
    numpy.random.seed(seed=2) 设置随机种子
    dataFrame.sample(n, frac, replace=False)

    dataFrame.groupby('class', group_keys) 根据对应的字段的值将 dataFrame 分组,从而获取 DataFrameGroupBy 实例。group_keys 指当 DataFrameGroupBy 实例调用 .apply() 函数时,是否添加分组字段的值到索引以便区分。DataFrameGroupBy 实例有属性: dataFrameGroupBy.groups 获取一个 dict,该 dict 以原 dataFrame 所指定 groupby 的字段的值为 key ,value 为对应值的行的索引的集合 dataFrameGroupBy.apply(funcName,...) 将分组后的每个 dataFrame 传入指定的函数作处理,该函数定义类似为 def funcName(dataFrame, *args, **kv) ,参数dataFrame 指传进的 dataFrame ,该 dataFrame 与一般 dataFrame 多了一个属性 .name ,指分组对应的字段的值,函数返回一个同参数一样结构的dataFrame。apply() 函数最终返回一个 DataFrame,作为各个分组应用处理后的 dataFrame 的重新整合
    # 按 class 列进行分组,得到一个分组对象
    gbr = data.groupby("class")
    # 获取所有分组字典 
    gbr.groups
    # 定义一个字典,指明每组需要抽取的个数
    typicalNDict = {
        1: 2, 
        2: 4, 
    # 定义分层抽样的方法
    def typicalSampling(group, typicalNDict):
        name = group.name
        n = typicalNDict[name]
        return group.sample(n=n)
    # 使用分组对象的 apply 方法
    result = data.groupby(
        'class', group_keys=False
    ).apply(typicalSampling, typicalNDict)
    # ==================================================
    # 按百分比的方式
    typicalFracDict = {
        1: 0.2, 
        2: 0.4, 
        3: 0.6
    def typicalSampling(group, typicalFracDict):
        name = group.name
        frac = typicalFracDict[name]
        return group.sample(frac=frac)
    result = data.groupby(
        'class', group_keys=False
    ).apply(typicalSampling, typicalFracDict)
    

    记录合并 —— 数据框的合并

    记录合并指将两个以上结构相同或不同的数据框,合并成一个数据框

    相关函数:

    concat([df1, df2,...]) 指记录的合并,即假设 df1 有m条记录,df2 有n条记录,则合并后有 m+n 条记录,索引为原来的索引,对于不同 DataFrame 字段不同的问题,则缺失的字段的值以 nan 填充
    import pandas
    from pandas import read_csv
    data1 = read_csv(
        'data1.csv', sep="|"
    data2 = read_csv(
        'data2.csv', sep="|"
    data3 = read_csv(
        'data3.csv', sep="|"
    data = pandas.concat([data1, data2, data3])
    # 当列名不一样时,合并后数据缺失部分填充为 nan
    data = pandas.concat([
        data1[[0, 1]], 
        data2[[1, 2]], 
        data3[[0, 2]]
    

    字段合并 —— 列的合并

    字段合并指将同意数据框中的不同列进行合并,形成新的列

    字段合并方法:x = x1 + x2 + ... (x 指数据列,Series)

    相关函数:

    dataFrame.astype(str) 将整个 dataFrame 元素的值的类型转化为 str
    from pandas import read_csv
    df = read_csv(
        'data.csv', 
        sep=" ", 
        names=['band', 'area', 'num']
    df = df.astype(str)
    tel = df['band'] + df['area'] + df['num']
    df['tel'] = tel
    

    字段匹配指根据各表共有的关键字段,把各表所需的记录一一对应起来。即把两个 dataFrame 关联起来

    相关函数:

  • merge(x,y,left_on,right_on)
  • series.max()
  • series.describe() 返回一个 Series ,索引为 count / mean / std / min / 25% / 50% / 75% / max,保存着对应的值
    import pandas
    data = pandas.read_csv(
        'data.csv'
    # round 取小数点后两位
    data['scale'] = round(
            data.score-data.score.min()
            data.score.max()-data.score.min()
    

    数组分组指根据数据分析对象的特征,按照一定的数值指标,把数据分析对象划分为不通的区间进行研究,以揭示其内在的联系和规律性

    主要针对如年龄这个字段,值比较分散,我们可以将其划分为如 [ '20以下', '20到40', '40到60', '60到80', '80到100', '100以上' ] ,以便做进一步的分析

    相关函数:

    pandas.cut(series, bins, right=True, labels=NULL) 返回一个 Series pandas.to_datetime(datetimeData, format) 当 datetimeData 为 str 时,返回一个 datetime,当为 series 时,返回一个 series
  • pandas.datetime.strptime(dates, '%Y%m%d')
  • data['时间.年'] = data['时间'].dt.year data['时间.月'] = data['时间'].dt.month data['时间.周'] = data['时间'].dt.weekday data['时间.日'] = data['时间'].dt.day data['时间.时'] = data['时间'].dt.hour data['时间.分'] = data['时间'].dt.minute data['时间.秒'] = data['时间'].dt.second

    时间抽取指按一定条件,对时间格式的数据进行抽取

    相关函数:

  • 根据索引进行抽取 dataFrame.ix 是 dataFrame 关于 index 的相关操作
  • dataFrame.ix[start: end] 表示获取 index 区间的行 dataFrame.ix[dates] 表示获取指定 list 的行
  • 根据时间列进行抽取
  • dataFrame[condition]
  • import pandas
    data = pandas.read_csv(
        'data.csv', 
        encoding='utf8'
    # 时间相关处理函数,str ==> datetime
    dateparse = lambda dates: pandas.datetime.strptime(dates, '%Y%m%d')
    # parse_dates 指定需要进行时间处理的字段,date_parser 指定时间处理函数,index_col 所指定的列作为索引
    data = pandas.read_csv(
        'data.csv', 
        encoding='utf8',
        parse_dates=['date'],
        date_parser=dateparse,
        index_col='date'
    
    #根据索引进行抽取
    import datetime
    # 创建两个 datatime 类型实例
    dt1 = datetime.date(year=2016,month=2,day=1);
    dt2 = datetime.date(year=2016,month=2,day=5);
    data.ix[dt1: dt2]
    # list ,指定要获取的 index
    data.ix[[dt1,dt2]]
    
    #根据时间列进行抽取
    data = pandas.read_csv(
        'data.csv', 
        encoding='utf8',
        parse_dates=['date'],
        date_parser=dateparse,
    data[(data.date>=dt1) & (data.date<=dt2)]
    

    虚拟变量,也叫哑变量和离散特征编码,可用来表示分类变量、非数量因素可能产生的影响

    虚拟变量的取值有两种:

  • 离散特征的取值之间有大小的意义,如尺寸(L XL S);
  • 离散特征的取值之间没有大小的意义,如颜色(红 蓝 绿)
  • 离散特征的取值之间有大小的意义的处理函数:pandas.Series.map(dict)series.map(dict) dict 以 series 的值为 key ,以要映射的值为 value,返回一个 Series

    离散特征的取值之间没有大小的意义的处理函数:pandas.get_dummies(data, prefix=None, prefix_sep='_'. dummy_na=False, columns=None, drop_first=False)

    # 可以看出 Education Level 取值之间有大小的意义,我们可以将之与具体的数值映射 data['Education Level'].drop_duplicates() 博士后 Post-Doc 博士 Doctorate 硕士 Master's Degree 学士 Bachelor's Degree 副学士 Associate's Degree 专业院校 Some College 职业学校 Trade School 高中 High School 小学 Grade School educationLevelDict = { 'Post-Doc': 9, 'Doctorate': 8, 'Master\'s Degree': 7, 'Bachelor\'s Degree': 6, 'Associate\'s Degree': 5, 'Some College': 4, 'Trade School': 3, 'High School': 2, 'Grade School': 1 data['Education Level Map'] = data[ 'Education Level' ].map( educationLevelDict # 可以看出 Gender 取值之间没有大小的意义 data['Gender'].drop_duplicates() 男 Male 女 Female 空值 nan # 这里离散值有 Male Female(忽略 nan),加上前缀和分隔符,生成两列 'Gender_Male' 、'Gender_Female' ,以 0或1 表示在原列中是否有对应的值,返回的 dataFrame 不包含原 'Gender' dummies = pandas.get_dummies( data, columns=['Gender'], prefix=['Gender'], prefix_sep="_", dummy_na=False,