2018-04-15-会一点点统计学的Pandas教程(二)

前言

淦,最近出第二语言的考试结果tm一周都没有开电脑。
再这样下去的话怕不是永远学不会Pandas了【笑】

上次写了一些基本操作【都坐下这只是基本操作】
然而......

【你学统计学怎么可以不回用Excel呢??】
我终究还是没有逃离Excel的魔掌,
看来我可能以后要用Python来做会计了qwq

正文

0x01 DataFrame选择数据

上次不是已经讲了自定义下标选择数据了嘛,然后自定义下标了嘛.....
那么取值范围呢,难不成切片嘛【为什么不可以切片??】

Pandas里面内置了很多有用的选择命令给我们来使用的x

好好好,一个一个来,我们先创建一个DataFrame
这里要复习一下了,一个DataFrame通常包括三个部分:

  • index 行索引
  • columns 列索引(注意这里有加s
  • nd-array 多维数组

这里来科普一下columns是什么【我老是记不住】:
column
美 [ˈkɑləm]
n.柱;栏目;纵队;(通常为)圆形石柱

说白了就是一个柱子【滑稽】

我们先来设置一个6*4的DataFrame:

>>> import numpy as np
>>> import pandas as pd

>>> date = pd.date_range('20180415',periods=6)
>>> ndarray = np.arange(24).reshape((6,4))
>>> column = ['A','B','C','D']

>>> df = pd.DataFrame(ndarray,index=date, columns=['A','B','C','D'])
>>> df
             A   B   C   D
2018-04-15   0   1   2   3
2018-04-16   4   5   6   7
2018-04-17   8   9  10  11
2018-04-18  12  13  14  15
2018-04-19  16  17  18  19
2018-04-20  20  21  22  23

严重警告!新手极其容易犯的错误【没有,我才没有犯过】

在定义date 的时候,千万千万不要为了偷懒(或者是不会写单词)而少写一个periods,这样很有可能导致定义失败,输出为空列表,切记切记

>>> date = pd.date_range('20180415',periods=6)
>>> date1 = pd.date_range('20180415',6)

>>> date
DatetimeIndex(['2018-04-15', '2018-04-16', '2018-04-17', '2018-04-18',
               '2018-04-19', '2018-04-20'],
              dtype='datetime64[ns]', freq='D')

>>> date1 #此处没有定义成功,输出为空列表
DatetimeIndex([], dtype='datetime64[ns]', freq='D')

经过一番周折终于定义好了一个DataFrame【才没有周折呢的说】

然后我们来试着在DataFrame里面选择数据,
在DataFrame里面除了上次我们说的那两种选择方式,还有一种是直接访问当前列的属性(会自动加入到属性里面来着):

>>> df['A'] #访问列标签(string)
2018-04-15     0
2018-04-16     4
2018-04-17     8
2018-04-18    12
2018-04-19    16
2018-04-20    20
Freq: D, Name: A, dtype: int32

>>> df.A #访问当前标签名字的属性
2018-04-15     0
2018-04-16     4
2018-04-17     8
2018-04-18    12
2018-04-19    16
2018-04-20    20
Freq: D, Name: A, dtype: int32


>>> df['A':'B']  # 访问行标签的切片(string) 完  全  失  败
Traceback (most recent call last):
........
ValueError: Given date string not likely a datetime.

>>> df['2018-04-15'] #访问当前行标签(string)完  全  失  败
Traceback (most recent call last):
.....
KeyError: '2018-04-15'

>>> df[0] #访问当前行下标 (列表) 完  全  失  败
Traceback (most recent call last):
........
KeyError: 0

>>> df[0:1] #访问当前行的切片(列表)   一  转  攻  势
            A  B  C  D
2018-04-15  0  1  2  3

>>> df['2018-04-15':'2018-04-16'] #访问行标签切片(string)
            A  B  C  D
2018-04-15  0  1  2  3
2018-04-16  4  5  6  7

>>> df[0:3]['A'] #组合访问测试  海  星
2018-04-15    0
2018-04-16    4
2018-04-17    8
Freq: D, Name: A, dtype: int32

# 得出结论:列标签可以访问单个元素,但是行标签最少访问两个元素
#如果是切片的话只能访问行标签(不加任何的其他命令)

看完这个强迫症就发作了有没有?
淦,如果你要访问A-C所有的元素岂不是还有去一个一个合并太麻烦了

所以开发者谁谁的也想到了.....

0x02 如何通过loc和iloc来选择数据

还是刚刚那个DataFrame,如果我们要向数组一样仅仅使用下标什么的访问:

>>> df[0][0]
Traceback (most recent call last):
........
KeyError: 0

美滋滋,这时候就需要使用上我们的loc和iloc了。
首先是loc,下面是bing词典上的定义,方便记忆:
loc
网络
代码行(line of code);行数;

在这里那这个命令代表着用标签的方法来定位元素【Pandas又不是神仙你会儿标签的一会儿下标的他也是会晕的】

用法如下,我们举一个简单的栗子,刚刚上面代码里面不能访问的横坐标标签'2018-04-15':

>>> df.loc['2018-04-15']
A    0
B    1
C    2
D    3
Name: 2018-04-15 00:00:00, dtype: int32
#PS:这里的连接符‘-’可以省略的哦

ddaada!现在可以访问了吧,现在再来实现我们刚刚做不到的访问A-C标签的所有元素,其实很简单,就像一个一次函数你只要给定xy的范围,电脑就会自动帮你把范围找出来【妈妈再也不会担心我的函数不等式写错了(幻视)】
用法:loc[横坐标切片,纵坐标切片] 全部就写:

>>> df.loc[:,'A':'B']
             A   B
2018-04-15   0   1
2018-04-16   4   5
2018-04-17   8   9
2018-04-18  12  13
2018-04-19  16  17
2018-04-20  20  21

这里的话很横坐标设置为无,然后纵坐标写一个A-B的切片,加上刚刚我们之前的loc便可以轻松达到我们直接单独访问标签或者标签属性达不到的效果【笑】
那么iloc呢,其实和loc是差不多的,但是关键的是你不用在写什么标签名了,可以直接写数组下标了厉不厉害?

>>> df.iloc[:,0]
2018-04-15     0
2018-04-16     4
2018-04-17     8
2018-04-18    12
2018-04-19    16
2018-04-20    20
Freq: D, Name: A, dtype: int32

>>> df.iloc[:,0:1] #这里0-1只会返回一个标签,因为后面一个标签是不算的
             A
2018-04-15   0
2018-04-16   4
2018-04-17   8
2018-04-18  12
2018-04-19  16
2018-04-20  20

有的人就想了:如果做一个df辣么大的话我到时候是不是还要一个一个找标签或者一个一个数下标呢

你可以把两种的定位方法混在一起用【虽然我平时都不这么干】
神奇ix,把两种方法写在一起的ex
虽然不怎么特别用,但是把loc和iloc替换成ix也是可以使用的【坏笑】
那我用他们两个干吗??

>>> df.ix[0:2:,'A':'C']
            A  B  C
2018-04-15  0  1  2
2018-04-16  4  5  6

0x03 添加数据【append?】

不在是apppend了,因为这次你连append的名字都不用写
直接写一个从来没有的属性名(或者标签名或者数组下标啥啥的)然后来一个等于
但是最要命的是,如果你添加的是一个矩阵的话一定要保证这个矩阵的对齐的,也

>>> df.ix[0:2:,'A':'C']
            A  B  C
2018-04-15  0  1  2
2018-04-16  4  5  6
>>> zeros = np.zeros((2,3),dtype = np.int) #这里保证对齐一下,不然出来一堆的NAN
>>> zeros
array([[0, 0, 0],
       [0, 0, 0]])
>>> df.ix[0:2:,'A':'C']=zeros
>>> df
             A   B   C   D
2018-04-15   0   0   0   3
2018-04-16   0   0   0   7
2018-04-17   8   9  10  11
2018-04-18  12  13  14  15
2018-04-19  16  17  18  19
2018-04-20  20  21  22  23

还有series什么的也是可以往里面加的,但是有的时候不对齐会出现很多很多的nan(无效值),处理NaN我下一次【没有下一次了】应该会讲到

不不不好吧我今天一次性写完【好困啊啊啊啊啊】

首先我们在原来的df上面添加一个全部都是NaN的列‘N'

>>> df['N']=np.nan
>>> df
             A   B   C   D   N
2018-04-15   0   0   0   3 NaN
2018-04-16   0   0   0   7 NaN
2018-04-17   8   9  10  11 NaN
2018-04-18  12  13  14  15 NaN
2018-04-19  16  17  18  19 NaN
2018-04-20  20  21  22  23 NaN

注意nan这个属性是Numpy里面的,写的时候千万不要写到Pandas里面了

如果想直接去掉有 NaN 的行或列, 可以使用 dropna【这个杀伤力太大了不建议使用】
把整个行直接去掉这么可怕的嘛

>>> df.dropna(
...     axis=0,     # 0: 对行进行操作; 1: 对列进行操作
...     how='any'   # 'any': 只要存在 NaN 就 drop 掉; 'all': 必须全部是 NaN 才 drop
...     )
Empty DataFrame
Columns: [A, B, C, D, N]
Index: []
# 对行进行操作【结果每行都有一个NaN】

>>> df.dropna(axis=1,how='any') #对列进行操作
             A   B   C   D
2018-04-15   0   0   0   3
2018-04-16   0   0   0   7
2018-04-17   8   9  10  11
2018-04-18  12  13  14  15
2018-04-19  16  17  18  19
2018-04-20  20  21  22  23

所以为什么不把所有的NaN值给换成0?
pd.fillna()
这个方法可以把所有的NaN的值给替换成任意你想要的数值【比如说是0】

下面借用一下morvanzhou的代码解释一下啦【woc学校里面不给装Python环境贼难受哦】

首先我们还是创建一个data frame,然后去其中的一些任意值为NaN

dates = pd.date_range('20130101', periods=6)
df = pd.DataFrame(np.arange(24).reshape((6,4)),index=dates, columns=['A','B','C','D'])
df.iloc[0,1] = np.nan
df.iloc[1,2] = np.nan
"""
             A     B     C   D
2013-01-01   0   NaN   2.0   3
2013-01-02   4   5.0   NaN   7
2013-01-03   8   9.0  10.0  11
2013-01-04  12  13.0  14.0  15
2013-01-05  16  17.0  18.0  19
2013-01-06  20  21.0  22.0  23
"""

接下来我们使用pd.fillna( )在把所有的NaN都替换成0

df.fillna(value=0)
"""
             A     B     C   D
2013-01-01   0   0.0   2.0   3
2013-01-02   4   5.0   0.0   7
2013-01-03   8   9.0  10.0  11
2013-01-04  12  13.0  14.0  15
2013-01-05  16  17.0  18.0  19
2013-01-06  20  21.0  22.0  23
"""

那么如果我要判断一个df里面是否存在无效值呢?
首先我们先把这个df给二值化(就是只分成有效和无效两种情况,分别用true和false来表示,如果用0和1也是可以的,然后我们遍历判断是否存在false

pd.isnull()
返回一个bool组成的列表
判断是否有缺失数据 NaN, 为 True 表示缺失数据:

df.isnull() 
"""
                A      B      C      D
2013-01-01  False   True  False  False
2013-01-02  False  False   True  False
2013-01-03  False  False  False  False
2013-01-04  False  False  False  False
2013-01-05  False  False  False  False
2013-01-06  False  False  False  False
"""

然后这时候你就可以遍历了,写一个什么for i in df:之类的.....

停一停Pandas已经给你做好了any模块来检测是否有false值
检测在数据中是否存在 NaN, 如果存在就返回 True:
不是什么如果存在就返回false,和遍历if什么都是不一样的辣

np.any(df.isnull()) == True  
# True

当让了,可以不借助 numpy 直接可以用pandas 自带的方法写:

 df.isnull().any().all()
# 如果只是判断列 df.isnull().any() 就可以

后记

写完了啊啊啊啊啊【一副熬夜脸】
最近出ESL,然后SAT和高斯还没停,只能在学校电脑上写Blog了淦
后半部分的代码都是抄的
没有啦没有啦没有啦真的是只是因为没有Py环境的啦

参考资料:
Pandas 处理丢失数据
Pandas 设置值
Pandas 选择数据
Pandas 官方教程'

最后的最后

真的真的是小姐姐不是女装dalao啊,Blog都没人看我可要伤心了

顺便说一句,jianshu这个markdown笔记本真tm好用qwq

你可能感兴趣的:(2018-04-15-会一点点统计学的Pandas教程(二))