【学习】Python pandas+numpy+可视化
20190605
一、pandas
pandas.png二、numpy
numpy.png三、可视化
可视化.png四、经典60题:
1、Python 中 (&,|)和(and,or)之间的区别
当比较变量为逻辑变量为,两种用法一致。当比较变量为数值变量为,则&, |表示位运算, and,or则依据是否非0来决定输出。
在pandas中,(df['Height']>200) | (df['Height']<170) 语句可以得到输出,(df['Height']>200) or(df['Height']<170)报错。姑且认为是|可以进行多变量比较,而or只能进行单变量比较。
image.png
2、Count the number of each type of animal in df.
df['animal'].value_counts()
3、pivot_table函数进行表的重建
For each animal type and each number of visits, find the mean age. In other words, each row is an animal, each column is a number of visits and the values are the mean ages (hint: use a pivot table).
df.pivot_table(values='age',index='animal',columns='visits') #以animal为索引,列为visits的各种值(有多少visits值,就有多少列),匹配的values为age的值
4、pandas+-*/的应用
how do you subtract the row mean from each element in the row?
df = pd.DataFrame(np.random.random(size=(5, 3)))
df.sub(df.mean(axis=1),axis=0)
5、返回column或index的最小值/最大值序号
Suppose you have DataFrame with 10 columns of real numbers, for example:
df = pd.DataFrame(np.random.random(size=(5, 10)), columns=list('abcdefghij'))
Which column of numbers has the smallest sum? (Find that column's label.)
df = pd.DataFrame(np.random.random(size=(5, 10)), columns=list('abcdefghij'))
df.sum().idxmin()
6、返回特定的column或index
返回column和index只有两个相关的函数dataframe.index 和dataframe.column(返回的是series),如果要把返回的index或者index用list表示,可以再加一层tolist()函数。
返回特定行或列,思路是“过滤+返回index”的方法,只是一般要用到loc/iloc函数,而不是直接索引(直接索引不能)
(2)返回特定列,思路其实是和返回行一样的,只是需要用到loc/iloc函数,用loc可以进行复杂操作:
import pandas as pd
items2 = [{'bikes': 20, 'pants': 30, 'watches': 35, 'shirts': 15, 'shoes':8, 'suits':45},
{'watches': 10, 'glasses': 50, 'bikes': 15, 'pants':5, 'shirts': 2, 'shoes':5, 'suits':7},
{'bikes': 20, 'pants': 30, 'watches': 35, 'glasses': 4, 'shoes':10}]
# 创建一个DataFrame并设置行索引
df = pd.DataFrame(items2, index = ['store 1', 'store 2', 'store 3'])
b=df.loc[:,df.isnull().sum(axis=0)==1].columns.tolist()
#返回该列具有一个nan值的列名称
为什么不能用直接索引方法?因为直接索引只能接受列名(或列名的list),或者是对应索引切片。
这里的df.isnull().sum(axis=0)==1 返回的是一个series,如果直接用df.[df.isnull().sum(axis=0)==1 ]是读不出来的,因为不接受series。换言之,如果是列名的list是可以读出来的。
所以,图方便,可以用直接索引处理特定行的筛选;对于特定列的筛选,只能用loc/iloc。
6、去除重复行/列
去除重复行有duplicate(返回重复行的索引)和drop_duplicate两种方法。可以指定特定的列,或者默认所有列去重。
去除重复列目前好像没有特定的方法?考虑用df.T进行转置,然后再去除重复行的方法??
7、pandas处理nan值
(1)、创建含有nan值的dataframe:
以下两种方式不能创建空值,因为默认为str
df=pd.DataFrame({'A':[1,2,3],'B':[1,2,3],'C':[1,2,3],'D':['','',''],'E':['','',''],'F':['','',''],'G':['','',''],'H':['','',''],'I':['','',''],'J':['','','']})
type(df.loc[1,'J']) #显示为str
df=pd.DataFrame({'A':[1,2,3],'B':[1,2,3],'C':[1,2,3]})
df['D']='NaN'
type(df.loc[1,'D']) #显示为str
以下是唯一创建空值的方法,返回的空值格式是numpy.float64,跟读取数据有关系吧?(不影响isnull使用,nan还是会返回True)
items2 = [{'bikes': 20, 'pants': 30, 'watches': 35, 'shirts': 15, 'shoes':8, 'suits':45},
{'watches': 10, 'glasses': 50, 'bikes': 15, 'pants':5, 'shirts': 2, 'shoes':5, 'suits':7},
{'bikes': 20, 'pants': 30, 'watches': 35, 'glasses': 4, 'shoes':10}]
df = pd.DataFrame(items2, index = ['store 1', 'store 2', 'store 3'])
df.loc['store 1','glasses'] #返回nan(不是NaN)
type(df.loc['store 1','glasses']) #返回 numpy.float64
(2)返回空值个数:
参见https://blog.csdn.net/Tyro_java/article/details/81396000
# 计算在store_items中NaN值的个数
x = store_items.isnull().sum().sum()
# 输出
print('在我们DataFrame中NaN的数量:', x)
在 Pandas 中,逻辑值 True 的数字值是 1,逻辑值 False 的数字值是 0。
因此,我们可以通过数逻辑值 True 的数量数出 NaN 值的数量。
为了数逻辑值 True 的总数,我们使用 .sum() 方法两次。
要使用该方法两次,是因为第一个 sum() 返回一个 Pandas Series,其中存储了列上的逻辑值 True 的总数
第二个 sum() 将上述 Pandas Series 中的 1 相加
可以使用 .count() 方法计算非空的总个数:
df.count().count()
count不同于sum,count只针对1/0进行处理,sum是对具体数值进行处理。
8、多索引groupby
For each group, find the sum of the three greatest values.
df = pd.DataFrame({'grps': list('aaabbcaabcccbbc'),
'vals': [12,345,3,1,45,14,4,52,54,23,235,21,57,3,87]})
#df.groupby(['grps'])['vals'].nlargest(3) #nlargest(3)构建了一个包含1级索引的新的dataframe,并且只含有最大的三个数
df.groupby(['grps'])['vals'].nlargest(3).sum(level=0)
尝试自己构建新列/索引用来表示排名(先用rank函数新建排名列,再筛选→groupby→sum):
df = pd.DataFrame({'grps': list('aaabbcaabcccbbc'),
'vals': [12,345,3,1,45,14,4,52,54,23,235,21,57,3,87]})
df['rank']=df.groupby(['grps'])['vals'].rank(method='dense',ascending=False)
(df[df.loc[:,'rank']<4].groupby(['grps'])['vals']).sum()
经典10套:
1、字符串处理为数值
Create a lambda function and change the type of item price:(原来的item_price格式是字符型,如$2.39)
用transform+匿名函数的方法,将字符串修改为float:
chipo['item_price']=chipo['item_price'].transform(lambda x:float(x[1:-1]))#这种方法比字符串转化要简单!
2、返回不重复行的总行数
最简单的方法是用value_counts()函数对行进行计数(计算重复出现了多少次),然后再进行行数统计:
chipo.item_name.value_counts().count()
如果要考虑groupby思想的话,那就必须用mean或者sum等函数把groupby后的groupby类型展开为dataframe(不然本身groupby类型不能进行计数的),再进行count:
chipo.groupby('item_name').sum().count()
3、panda关于字符串处理的函数
Select the teams that start with G
自己的写法:
euro12[euro12.Goals>6].Team
但实际上panda有字符串首、末的函数
euro12[euro12.Team.str.startswith('G')]
4、loc/iloc用于筛选行名/列名,如何筛选列里面的值?
Present only the Shooting Accuracy from England, Italy and Russia
一种方法是用判断语句(euro12.Team=='England'&...),再返回进行索引。缺点在于筛选值比较多的时候,要用很多“或”语句,很臃肿。
另一种简便的方法是直接用isin函数,再返回进行索引
euro12.loc[euro12.Team.isin(['England', 'Italy', 'Russia']), ['Team','Shooting Accuracy']]
5、stack和unstack方法
https://www.cnblogs.com/bambipai/p/7658311.html
6、groupby后直接打印group的方法(有点像enumerate可以返回序数和值)
# Group the dataframe by regiment, and for each regiment,
for name, group in regiment.groupby('regiment'):
# print the name of the regiment
print(name)
# print the data of that regiment
print(group)
直接用name 和 group(没有找到这个函数,但实际上name就是对应group名,group对应所包含的组的内容!!)。
这可能是唯一的办法,不然的话要用 for index in regiment.groupby('regiment'),再依次print 该某类'regiment'下所有的index对应的行?然而'regiment'和'index'都没有对应的函数!!???
7、agg、transform、apply、applymap、map的比较
(1) agg只能用自带函数(mean、sum这些)进行数值运算,允许不同列进行不同运算;
(2)transform允许:匿名函数+自带函数(mean、sum这些)+自定义函数,只允许对单列进行单个/多个运算;
(3)apply允许:匿名函数+自定义函数,相比transform不允许自带函数,同时是以series作为计算单位的(当只有一个series时,可以是针对每个数据的单独运算,当是一组series时,则必须是min、max这种聚集函数);
(4)applymap是以所有元素进行运算的;
(5)map是针对series的每个元素进行运算的。
关于apply、applymap、map参https://blog.csdn.net/u010814042/article/details/76401133
总结:要进行自带函数运算,用agg和transform,进行自定义函数运算,apply、applymap、map各有用处,但是如果是针对多列进行不同的自定义函数运算,只有遍历方法。
8、转换为时间格式dateme64
https://blog.csdn.net/qq_36523839/article/details/79746977
用pd.to_datetime函数要记得匹配原数据中的时间格式:
· 1/17/07 has the format "%m/%d/%y"
· 17-1-2007 has the format "%d-%m-%Y"
9、生成随机整数,要用np.random.randint()函数
10、np.random.rand和np.random.random的区别
https://blog.csdn.net/xia_ri_xing/article/details/82949004
其实没有区别,就是输入的是元祖还是数字组合的区别
11、concat、union、append和merge
mysql的union和pd.append差不多,都是组成更多的行
pd.concat既可以组成行,也可以扩展成列,所以综合来说最方便。
pd.concat相比merge:merge是正宗的表的联结,concat只能是表的组合,不具备根据某列进行join的功能,而且concat的join也只是针对联结的两个表,连接后是保留原来表所有的columns(outer),还是保留两个都有的columns(inner)。所以concat的join是对列说的,merge的join是对行数据来说的。
12、处理dataframe或者series多级索引的方式
series如果存在多级索引很难提取,可以先to_frame转化成dataframe,再reset_index,把多级转化成column,再提取列名;
dataframe里面的列如果要重新设置为多级索引,有一个dataframe.columns=pd.MultiIndex.from_product()的方法