开发者社区> 问答> 正文

怎么用python分析数据分析

怎么用python分析数据分析

展开
收起
云计算小粉 2018-05-10 20:11:06 2274 0
2 条回答
写回答
取消 提交回答
  • 第三方包

    pandas

    numpy

    了解一下。

    2019-11-22 14:49:40
    赞同 展开评论 打赏
  • 流处理,听起来很高大上啊,其实就是分块读取。有这么一些情况,有一个很大的几个G的文件,没办法一次处理,那么就分批次处理,一次处理1百万行,接着处理下1百万行,慢慢地总是能处理完的。

    使用类似迭代器的方式

    data=pd.read_csv(file, chunksize=1000000)
    for sub_df in data:

    print('do something in sub_df here')

    1
    2
    3
    4
    索引

    Series和DataFrame都是有索引的,索引的好处是快速定位,在涉及到两个Series或DataFrame时可以根据索引自动对齐,比如日期自动对齐,这样可以省去很多事。

    缺失值

    pd.isnull(obj)
    obj.isnull()
    1
    2
    将字典转成数据框,并赋予列名,索引

    DataFrame(data, columns=['col1','col2','col3'...],

            index = ['i1','i2','i3'...])

    1
    2
    查看列名

    DataFrame.columns

    查看索引

    DataFrame.index

    重建索引

    obj.reindex(['a','b','c','d','e'...], fill_value=0]

    按给出的索引顺序重新排序,而不是替换索引。如果索引没有值,就用0填充

    就地修改索引

    data.index=data.index.map(str.upper)
    1
    2
    3
    4
    5
    列顺序重排(也是重建索引)

    DataFrame.reindex[columns=['col1','col2','col3'...])`

    也可以同时重建index和columns

    DataFrame.reindex[index=['a','b','c'...],columns=['col1','col2','col3'...])
    1
    2
    3
    4
    5
    重建索引的快捷键

    DataFrame.ix[['a','b','c'...],['col1','col2','col3'...]]
    1
    重命名轴索引

    data.rename(index=str.title,columns=str.upper)

    修改某个索引和列名,可以通过传入字典

    data.rename(index={'old_index':'new_index'},

            columns={'old_col':'new_col'})

    1
    2
    3
    4
    5
    查看某一列

    DataFrame['state'] 或 DataFrame.state
    1
    查看某一行

    需要用到索引

    DataFrame.ix['index_name']
    1
    添加或删除一列

    DataFrame['new_col_name'] = 'char_or_number'

    删除行

    DataFrame.drop(['index1','index2'...])

    删除列

    DataFrame.drop(['col1','col2'...],axis=1)

    del DataFrame['col1']
    1
    2
    3
    4
    5
    6
    7
    DataFrame选择子集

    类型 说明
    obj[val] 选择一列或多列
    obj.ix[val] 选择一行或多行
    obj.ix[:,val] 选择一列或多列
    obj.ix[val1,val2] 同时选择行和列
    reindx 对行和列重新索引
    icol,irow 根据整数位置选取单列或单行
    get_value,set_value 根据行标签和列标签选择单个值
    针对series

    obj[['a','b','c'...]]
    obj['b':'e']=5
    1
    2
    针对dataframe

    选择多列

    dataframe[['col1','col2'...]]

    选择多行

    dataframe[m:n]

    条件筛选

    dataframe[dataframe['col3'>5]]

    选择子集

    dataframe.ix[0:3,0:5]
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    dataframe和series的运算

    会根据 index 和 columns 自动对齐然后进行运算,很方便啊

    方法 说明
    add 加法
    sub 减法
    div 除法
    mul 乘法

    没有数据的地方用0填充空值

    df1.add(df2,fill_value=0)

    dataframe 与 series 的运算

    dataframe - series

    规则是:
    --------
    v

    指定轴方向

    dataframe.sub(series,axis=0)
    规则是:
    -------- ---
    | | | | ----->
    | | | |
    | | | |
    | | | |
    -------- ---
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    apply函数

    f=lambda x:x.max()-x.min()

    默认对每一列应用

    dataframe.apply(f)

    如果需要对每一行分组应用

    dataframe.apply(f,axis=1)
    1
    2
    3
    4
    5
    6
    7
    排序和排名

    默认根据index排序,axis = 1 则根据columns排序

    dataframe.sort_index(axis=0, ascending=False)

    根据值排序

    dataframe.sort_index(by=['col1','col2'...])

    排名,给出的是rank值

    series.rank(ascending=False)

    如果出现重复值,则取平均秩次

    在行或列上面的排名

    dataframe.rank(axis=0)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    描述性统计

    方法 说明
    count 计数
    describe 给出各列的常用统计量
    min,max 最大最小值
    argmin,argmax 最大最小值的索引位置(整数)
    idxmin,idxmax 最大最小值的索引值
    quantile 计算样本分位数
    sum,mean 对列求和,均值
    mediam 中位数
    mad 根据平均值计算平均绝对离差
    var,std 方差,标准差
    skew 偏度(三阶矩)
    Kurt 峰度(四阶矩)
    cumsum 累积和
    Cummins,cummax 累计组大致和累计最小值
    cumprod 累计积
    diff 一阶差分
    pct_change 计算百分数变化
    唯一值,值计数,成员资格

    obj.unique()
    obj.value_count()
    obj.isin(['b','c'])
    1
    2
    3
    处理缺失值

    过滤缺失值

    只要有缺失值就丢弃这一行

    dataframe.dropna()

    要求全部为缺失才丢弃这一行

    dataframe.dropna(how='all')

    根据列来判断

    dataframe.dropna(how='all',axis=1)

    填充缺失值

    1.用0填充

    df.fillna(0)

    2.不同的列用不同的值填充

    df.fillna({1:0.5, 3:-1})

    3.用均值填充

    df.fillna(df.mean())

    此时axis参数同前面,

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    将列转成行索引

    df.set_index(['col1','col2'...])
    1
    数据清洗,重塑

    合并数据集

    取 df1,df2 都有的部分,丢弃没有的

    默认是inner的连接方式

    pd.merge(df1,df2, how='inner')

    如果df1,df2的连接字段名不同,则需要特别指定

    pd.merge(df1,df2,left_on='l_key',right_on='r_key')

    其他的连接方式有 left,right, outer等。

    如果dataframe是多重索引,根据多个键进行合并

    pd.merge(left, right, on=['key1','key2'],how = 'outer')

    合并后如果有重复的列名,需要添加后缀

    pd.merge(left, right, on='key1', suffixes=('_left','_right'))
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    索引上的合并

    针对dataframe中的连接键不是列名,而是索引名的情况。

    pd.merge(left, right, left_on = 'col_key', right_index=True)

    即左边的key是列名,右边的key是index。

    多重索引

    pd.merge(left, right, left_on=['key1','key2'], right_index=True)
    1
    2
    3
    4
    5
    6
    dataframe的join方法

    实现按索引合并。

    其实这个join方法和数据库的join函数是以一样的理解

    left.join(right, how='outer')

    一次合并多个数据框

    left.join([right1,right2],how='outer')
    1
    2
    3
    4
    5
    6
    轴向连接(更常用)

    连接:concatenation
    绑定:binding
    堆叠:stacking
    列上的连接

    np.concatenation([df1,df2],axis=1) #np包
    pd.concat([df1,df2], axis=1) #pd包

    和R语言中的 cbind 是一样的

    如果axis=0,则和 rbind 是一样的

    索引对齐,没有的就为空

    join='inner' 得到交集

    pd.concat([df1,df2], axis=1, join='innner')

    keys 参数,还没看明白

    ignore_index=True,如果只是简单的合并拼接而不考虑索引问题。

    pd.concat([df1,df2],ignore_index=True)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    合并重复数据

    针对可能有索引全部或者部分重叠的两个数据集

    填充因为合并时索引赵成的缺失值

    where函数

    where即if-else函数

    np.where(isnull(a),b,a)
    1
    2
    combine_first方法

    如果a中值为空,就用b中的值填补

    a[:-2].combine_first(b[2:])

    combine_first函数即对数据打补丁,用df2的数据填充df1中的缺失值

    df1.combine_first(df2)
    1
    2
    3
    4
    5
    重塑层次化索引

    stact:将数据转为长格式,即列旋转为行
    unstack:转为宽格式,即将行旋转为列
    result=data.stack()
    result.unstack()
    1
    2
    长格式转为宽格式

    pivoted = data.pivot('date','item','value')

    前两个参数分别是行和列的索引名,最后一个参数则是用来填充dataframe的数据列的列名。如果忽略最后一个参数,得到的dataframe会带有层次化的列。

    1
    2
    3
    透视表

    table = df.pivot_table(values=["Price","Quantity"],

            index=["Manager","Rep"],
            aggfunc=[np.sum,np.mean],
            margins=True))
    

    values:需要对哪些字段应用函数

    index:透视表的行索引(row)

    columns:透视表的列索引(column)

    aggfunc:应用什么函数

    fill_value:空值填充

    margins:添加汇总项

    然后可以对透视表进行筛选

    table.query('Manager == ["Debra Henley"]')
    table.query('Status == ["pending","won"]')
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    移除重复数据

    判断是否重复

    data.duplicated()`

    移除重复数据

    data.drop_duplicated()

    对指定列判断是否存在重复值,然后删除重复数据

    data.drop_duplicated(['key1'])
    1
    2
    3
    4
    5
    6
    7
    8
    9
    交叉表

    是一种用于计算分组频率的特殊透视表.
    注意,只对离散型的,分类型的,字符型的有用,连续型数据是不能计算频率这种东西的。

    pd.crosstab(df.col1, df.col2, margins=True)
    1
    类似vlookup函数

    利用函数或映射进行数据转换

    1.首先定义一个字典

    meat_to_animal={

    'bacon':'pig',
    'pulled pork':'pig',
    'honey ham':'cow'

    }

    2.对某一列应用一个函数,或者字典,顺便根据这一列的结果创建新列

    data['new_col']=data['food'].map(str.lower).map(meat_to_animal)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    替换值

    data.replace(-999,np.na)

    多个值的替换

    data.replace([-999,-1000],np.na)

    对应替换

    data.replace([-999,-1000],[np.na,0])

    对应替换也可以传入一个字典

    data.replace({-999:np.na,-1000:0})
    1
    2
    3
    4
    5
    6
    7
    8
    9
    离散化

    定义分割点

    简单分割(等宽分箱)

    s=pd.Series(range(100))
    pd.cut(s, bins=10, labels=range(10))

    bins=[20,40,60,80,100]

    切割

    cats = pd.cut(series,bins)

    查看标签

    cats.labels

    查看水平(因子)

    cats.levels

    区间计数

    pd.value_count(cats)

    自定义分区的标签

    group_names=['youth','youngAdult','MiddleAge','Senior']
    pd.cut(ages,bins,labels=group_names)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    分位数分割

    data=np.random.randn(1000)
    pd.qcut(data,4) #四分位数

    自定义分位数,包含端点

    pd.qcut(data,[0,0.3,0.5,0.9,1])
    1
    2
    3
    4
    5
    异常值

    查看各个统计量

    data.describe()

    对某一列

    col=data[3]
    col[np.abs(col)>3]

    选出全部含有“超过3或-3的值的行

    data[(np.abs(data)>3).any(1)]

    异常值替换

    data[np.abs(data)>3]=np.sign(data)*3
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    抽样

    随机抽取k行

    df.take(np.random.permutation(len(df))[:k])

    随机抽取k行,但是k可能大于df的行数

    可以理解为过抽样了

    df.take(np.random.randint(0,len(df),size=k))
    1
    2
    3
    4
    5
    6
    7
    数据摊平处理

    相当于将类别属性转成因子类型,比如是否有车,这个字段有3个不同的值,有,没有,过段时间买,那么将会被编码成3个字段,有车,没车,过段时间买车,每个字段用0-1二值填充变成数值型。

    对摊平的数据列增加前缀

    dummies = pd.get_dummies(df['key'],prefix='key')

    将摊平产生的数据列拼接回去

    df[['data1']].join(dummies)
    1
    2
    3
    4
    5
    字符串操作

    拆分

    strings.split(',')

    根据正则表达式切分

    re.split('s+',strings)

    连接

    'a'+'b'+'c'...
    或者
    '+'.join(series)

    判断是否存在

    's' in strings`
    strings.find('s')

    计数

    strings.count(',')

    替换

    strings.replace('old','new')

    去除空白字符

    s.strip()
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    正则表达式

    正则表达式需要先编译匹配模式,然后才去匹配查找,这样能节省大量的CPU时间。

    re.complie:编译
    findall:匹配所有
    search:只返回第一个匹配项的起始和结束地址
    match:值匹配字符串的首部
    sub:匹配替换,如果找到就替换

    原始字符串

    strings = 'sdf@153.com,dste@qq.com,sor@gmail.com'

    编译匹配模式,IGNORECASE可以在使用的时候对大小写不敏感

    pattern = r'[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}'
    regex = re.compile(pattern,flags=re.IGNORECASE)

    匹配所有

    regex.findall(strings)

    使用search

    m = regex.search(strings) #获取匹配的地址
    strings[m.start():m.end()]

    匹配替换

    regex.sub('new_string', strings)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    根据模式再切分

    将模式切分,也就是将匹配到的进一步切分,通过pattern中的括号实现.

    pattern = r'([A-Z0-9._%+-]+)@([A-Z0-9.-]+)\.([A-Z]{2,4})'
    regex = re.compile(pattern)
    regex.findall(strings)

    如果使用match

    m=regex.match(string)
    m.groups()

    效果是这样的

    suzyu123@163.com --> [(suzyu123, 163, com)]

    获取 list-tuple 其中的某一列

    matches.get(i)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    分组聚合,计算

    group_by技术

    根据多个索引分组,然后计算均值

    means = df['data1'].groupby([df['index1'],df['index2']).mean()

    展开成透视表格式

    means.unstack()
    1
    2
    3
    4
    5
    分组后价将片段做成一个字典

    pieces = dict(list(df.groupby('index1')))

    pieces['b']
    1
    2
    3
    groupby默认是对列(axis=0)分组,也可以在行(axis=1)上分组

    语法糖,groupby的快捷函数

    df.groupby('index1')['col_names']
    df.groupby('index1')[['col_names']]

    是下面代码的语法糖

    df['col_names'].groupby(df['index1'])

    df.groupby(['index1','index2'])['col_names'].mean()
    1
    2
    3
    4
    5
    6
    7
    通过字典或series进行分组

    people = DataFrame(np.random.randn(5, 5),

                    columns=['a', 'b', 'c', 'd', 'e'],
                    index=['Joe', 'Steve', 'Wes', 'Jim','Travis'])
    

    选择部分设为na

    people.ix[2:3,['b','c']]=np.na

    mapping = {'a': 'red', 'b': 'red', 'c': 'blue',

            'd': 'blue', 'e': 'red', 'f' : 'orange'}
    

    people.groupby(mapping,axis=1).sum()
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    通过函数进行分组

    根据索引的长度进行分组

    people.groupby(len).sum()
    1
    2
    数据聚合

    使用自定义函数

    对所有的数据列使用自定义函数

    df.groupby('index1').agg(myfunc)

    使用系统函数

    df.groupby('index1')['data1']describe()
    1
    2
    3
    4
    5
    根据列分组应用多个函数

    分组

    grouped = df.groupby(['col1','col2'])

    选择多列,对每一列应用多个函数

    grouped['data1','data2'...].agg(['mean','std','myfunc'])
    1
    2
    3
    4
    5
    对不同列使用不同的函数

    grouped = df.groupby(['col1','col2'])

    传入一个字典,对不同的列使用不同的函数

    不同的列可以应用不同数量的函数

    grouped.agg({'data1':['min','max','mean','std'],

                'data2':'sum'})

    1
    2
    3
    4
    5
    6
    分组计算后重命名列名

    grouped = df.groupby(['col1','col2'])

    grouped.agg({'data1':[('min','max','mean','std'),('d_min','d_max','d_mean','d_std')],

                'data2':'sum'})

    1
    2
    3
    4
    返回的聚合数据不要索引

    df.groupby(['sex','smoker'], as_index=False).mean()
    1
    分组计算结果添加前缀

    对计算后的列名添加前缀

    df.groupby('index1').mean().add_prefix('mean_')
    1
    2
    将分组计算后的值替换到原数据框

    将函数应用到各分组,再将分组计算的结果代换原数据框的值

    也可以使用自定义函数

    df.groupby(['index1','index2'...]).transform(np.mean)
    1
    2
    3
    更一般化的apply函数

    df.groupby(['col1','col2'...]).apply(myfunc)

    df.groupby(['col1','col2'...]).apply(['min','max','mean','std'])
    1
    2
    3
    禁用分组键

    分组键会跟原始对象的索引共同构成结果对象中的层次化索引

    df.groupby('smoker', group_keys=False).apply(mean)
    1
    分组索引转成df的列

    某些情况下,groupby的as_index=False参数并没有什么用,得到的还是一个series,这种情况一般是尽管分组了,但是计算需要涉及几列,最后得到的还是series,series的index是层次化索引。这里将series转成dataframe,series的层次化索引转成dataframe的列。

    def fmean(df):

    """需要用两列才能计算最后的结果"""
    skus=len(df['sku'].unique())
    sums=df['salecount'].sum()
    return sums/skus
    

    尽管禁用分组键,得到的还是series

    salemean=data.groupby(by=['season','syear','smonth'],as_index=False).apply(fmean)

    将series转成dataframe,顺便设置索引

    sub_df = pd.DataFrame(salemean.index.tolist(),columns=salemean.index.names,index=salemean.index)

    将groupby的结果和sub_df合并

    sub_df['salemean']=salemean
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    桶分析与分位数

    对数据切分段,然后对每一分段应用函数

    frame = DataFrame({'col1':np.random.randn(1000),

                    'col2':np.random.randn(1000)})
    

    数据分段,创建分段用的因子

    返回每一元素是属于哪一分割区间

    factor = pd.cut(frame.col1, 4)

    分组计算,然后转成数据框形式

    grouped = frame.col2.groupby(factor)
    grouped.apply(myfunc).unstack()
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    用分组的均值填充缺失值

    自定义函数

    fill_mean= lambda x:x.fillna(x.mean())

    分组填充

    df.groupby(group_key).apply(fill_mean)
    1
    2
    3
    4
    5
    分组后不同的数据替换不同的值

    定义字典

    fill_value = {'east':0.5, 'west':-1}

    定义函数

    fill_func = lambda x:x.fillna(fill_value(x.name))

    分组填充

    df.groupby(['index1','index2'...]).apply(fill_func)
    1
    2
    3
    4
    5
    6
    7
    8
    sql操作

    有时候觉得pandas很方便,但是有时候却很麻烦,不如SQL方便。因此pandas中也有一些例子,用pandas实现SQL的功能,简单的就不说了,下面说些复杂点的操作。
    之所以说这个复杂的语句,是因为不想将这些数据操作分写在不同的语句中,而是从头到尾连续编码实现一个功能。
    SQL复杂操作用到的主要函数是assign,简单说其实和join的功能是一样的,根据df1,df2的索引值来将df2拼接到df1上。
    两个函数是query,也听方便的。

    有一批销量数据,筛选出那些有2个月以上的销量产品的数据,说白了就是剔除那些新上市产品的数据

    方法是先统计每个产品的数据量,然后选出那些数据量>2的产品,再在数据表中选择这些产品

    sku smonth

    a 1

    a 2

    a 3

    a 4

    b 5

    b 6

    b 7

    b 8

    c 9

    c 10

    按sku分组,统计smonth的次数,拼接到salecount中,然后查询cnt>2的

    salecount.assign(cnt=salecount.groupby(['sku'])['smonth'].count()).query('cnt>2')

    2019-07-17 22:25:37
    赞同 展开评论 打赏
问答排行榜
最热
最新

相关电子书

更多
From Python Scikit-Learn to Sc 立即下载
Data Pre-Processing in Python: 立即下载
双剑合璧-Python和大数据计算平台的结合 立即下载