pandas 最有趣的地方在于里面隐藏了很多包。它是一个核心包,里面有很多其他包的功能。这点很棒,因为你只需要使用 pandas 就可以完成工作。pandas 相当于 python 中 excel:它使用表(也就是 dataframe),能在数据上做各种变换,但还有其他很多功能。
文章目录
- DataFrame的创建
- DataFrame的相关操作
* - DataFrame的基本属性和方法
– - DataFrame的基本数据操作
- DataFrame的高级索引loc、iloc
- DataFrame的运算
– - apply(),applymap(),map()函数
- 数据合并(concat,merge)
– - 分组和聚合
- 交叉表与透视表(没怎么用过)
- 实操中遇到的问题及其解决办法
* - 统计某列无重复的值
- 统计指定列不重复的值的数目
– - 遍历dataframe的每一行方法比较总结
– - SettingWithCopyWarning警告
–
DataFrame的创建
操作代码实现返回值说明通过ndarray构建DataFramepd.DataFrame(array)
pd.DataFrame(np.random.randn(3,4), columns = [‘a’, ‘b’, ‘c’])新DataFrame通过Numpy的ndarray构建,
自动生成行列索引,
columns 可指定列索引名通过dict构建DataFramepd.DataFrame(dict)
dict = {‘A’: 1,
‘B’: pd.Timestamp(‘20190616’),
‘C’:pd.Series(1,index=list(range(4)),dtype=’float32′),
‘D’: np.array([3] * 4,dtype=’int32′),
‘E’: [“Python”,”Java”,”C++”,”C”],
‘F’: ‘tiger’ }新DataFramedict的key为列标签
value为元素
自动生成行索引
DataFrame的相关操作
DataFrame的基本属性和方法
读数据
常用读取文件函数 read_csv, read_excel,read_clipboard, read_sql
如:data = pd.read_csv( my_file.csv , sep= ; , encoding= latin-1 , nrows=1000, skiprows=[2,5])
注:sep 代表的是分隔符。如果你在使用法语数据,excel 中 csv 分隔符是「;」,因此你需要显式地指定它。编码设置为 latin-1 来读取法语字符。nrows=1000 表示读取前 1000 行数据。skiprows=[2,5] 表示你在读取文件的时候会移除第 2 行和第 5 行。
写数据
data.to_csv( my_new_file.csv , index=None)
注:index=None 表示将会以数据本来的样子写入。如果没有写 index=None,你会多出一个第一列,内容是 1,2,3,…,一直到最后一行。
其他的写入函数.to_excel, .to_json, .to_pickle
检查数据
Gives (#rows, #columns) 给出行数和列数
data.describe() 计算基本的统计数据
查看数据
从头查看数据 head()
data.head() 默认返回5行 返回值为DataFrame
head( n ) 方法用于读取前面的 n 行,如果不填参数 n ,默认返回 5 行
从尾查看数据 tail ( )
data.tail() 默认返回5行 返回值为DataFrame
tail( n ) 方法用于读取尾部的 n 行,如果不填参数 n ,默认返回 5 行,空行各个字段的值返回 NaN。
数据形状 shape
data.shape 获取数据形状 返回值为元组
假设data为10行8列的数据 则返回(10,8)
扩展:在机器学习与深度学习模型中,需要将数据集划分为训练集和测试集会造成索引的混乱
可以通过shape方法让索引重新有序
如: data.index = range(data.shape[0])
也可以使用data.reset_index(drop=True)
转置 T
data.T 进行数据转置 返回值为DataFrame 不改变原来的DataFrame
假设data为10行8列的数据 则返回8行10列的数据
设置index(整体全部修改)
data.index = list 整体全部修改index 返回值为DataFrame 不改变原来的DataFrame
说明:按照列表list的数据内容修改index,必须整体全部修改
错误示例:data.index[3] = ‘学生_3’
重新设新的下标索引
data.reset_index(drop=True) 重新设新的下标索引 返回值为DataFrame 不改变原来的DataFrame
说明:drop:默认为False,不删除原来索引,如果为True,删除原来的索引值
一般适用于索引发生混乱的时候,给索引重新从0编号
把某列值设置为新的索引
data.set_index(keys, drop=True) 把某列值设置为新的索引 返回值为DataFrame 不改变原来的DataFrame
说明:keys : 列索引名成或者列索引名称的列表 drop: 默认为False,不删除原来索引,如果为True,删除原来的索引值
获取 DataFrame 的简要摘要
data.info() 返回DataFrame的一些基本信息
DataFrame的基本数据操作
操作代码实现返回值说明删除若干列df.drop([“a”,”b”,”c”], axis=1)新DataFrame不改变原来的DataFrame删除列数据del(df[‘G’])None改变原来的DataFrame增加列数据df[‘G’]=listDataFrame改变原来的DataFrame,list的长度必须的保持一致对某一列重新赋值df[‘G’]=100DataFrame改变原来的DataFrame对值排序df.sort_values(by=”open”, ascending=False)
df.sort_values(by=[‘open’, ‘high’])DataFrame改变原来的DataFrame
by:指定排序参考的键,单个键或者多个键进行排序
ascending:默认True升序,False降序对某一列重新赋值df[‘G’]=100DataFrame改变原来的DataFrame对索引排序df.sort_index()DataFrame改变原来的DataFrame
ascending:默认True升序,False降序
DataFrame的高级索引loc、iloc
loc函数:通过行索引 “Index” 中的具体值来取行数据(如取”Index”为”A”的行)
iloc函数:通过行号来取行数据(如取第二行的数据)
本章给出loc、iloc常见的五种用法,并附上详细代码。
1. 利用loc、iloc提取行数据
import numpy as np
import pandas as pd
data=pd.DataFrame(np.arange(16).reshape(4,4),index=list('abcd'),columns=list('ABCD'))
In[1]: data
Out[1]:
A B C D
a 0 1 2 3
b 4 5 6 7
c 8 9 10 11
d 12 13 14 15
In[2]: data.loc['a']
Out[2]:
A 0
B 1
C 2
D 3
In[3]: data.iloc[0]
Out[3]:
A 0
B 1
C 2
D 3
2. 利用loc、iloc提取列数据
In[4]:data.loc[:,['A']]
Out[4]:
A
a 0
b 4
c 8
d 12
In[5]:data.iloc[:,'A':'C']
Out[5]:
A B C
a 0 1 2
b 4 5 6
c 8 9 10
d 12 13 14
In[6]:data.iloc[:,[0]]
Out[6]:
A
a 0
b 4
c 8
d 12
In[7]:data.iloc[:,0:2]
Out[7]:
A B
a 0 1
b 4 5
c 8 9
d 12 13
3.利用loc、iloc提取指定行、指定列数据
In[8]:data.loc[['a','b'],['A','B']]
Out[8]:
A B
a 0 1
b 4 5
In[9]:data.loc['b':'d','A':'C']
Out[9]:
A B C
b 4 5 6
c 8 9 10
d 12 13 14
In[9]:data.iloc[[0,1],[0,1]]
Out[9]:
A B
a 0 1
b 4 5
In[10]:data.iloc[1:4,0:3]
Out[10]:
A B C
b 4 5 6
c 8 9 10
d 12 13 14
4.利用loc、iloc提取所有数据
In[11]:data.loc[:,:]
Out[11]:
A B C D
a 0 1 2 3
b 4 5 6 7
c 8 9 10 11
d 12 13 14 15
In[12]:data.iloc[:,:]
Out[12]:
A B C D
a 0 1 2 3
b 4 5 6 7
c 8 9 10 11
d 12 13 14 15
5.利用loc函数,根据某个数据来提取数据所在的行
In[13]: data.loc[data['A']==0]
Out[13]:
A B C D
a 0 1 2 3
In[14]: data.loc[(data['A']==0)&(data['B']==2)]
Out[14]:
A B C D
a 0 1 2 3
同时,以下几种写法也可提取数据所在的行,与第五种用法类似,仅作补充。
In[15]: data[data['A']==0]
In[16]: data[data['A'].isin([0])]
In[17]: data[(data['A']==0)&(data['B']==2)]
In[18]: data[(data['A'].isin([0]))&(data['B'].isin([2]))]
Out[15]:
A B C D
DataFrame的运算
a. 运算函数
操作代码实现返回值说明算术运算df[‘open’].add(100)
df[‘open’].sub(100)新Series不改变原来的DataFrame,实际上是Series运算
add(100)是该列每一行的元素都+100
sub(100)是该列每一列的元素都-100逻辑运算df[“open”] > 100新Series(bool类型)不改变原来的DataFrame,返回值是True与Flase的Serise筛选df[df[“open”] > 23]
df[(df[“open”] > 23) & (df[“open”] < 24)]新DataFrame逻辑判断的结果可以作为筛选的依据筛选函数query()df.query(“open
b.统计运算函数
有时候我们获取到数据之后,想要查看下数据的简单统计指标(最大值、最小值、平均值、中位数等),比如想要查看年龄的最大值,如何实现呢?直接对 age
这一列调用 max
方法即可。
user_info.age.max()
类似的,通过调用 min
、 mean
、 quantile
、 sum
方法可以实现最小值、平均值、中位数以及求和
累加求和 cumsum ( )
来介绍个有意思的方法: cumsum
,看名字就发现它和 sum
方法有关系,事实上确实如此, cumsum
也是用来求和的,不过它是用来累加求和的,也就是说它得到的结果与原始的 DataFrame 大小相同。 cummax
最后的结果就是将上一次求和的结果与原始当前值求和作为当前值。 cumsum
也可以用来操作字符串类型的对象。
一次性获取多个统计指标 describe( )
data.describe()
返回结果如图
如果想要查看非数字类型的列的统计指标,可以设置
include=["object"]
来获得。count:总数
unique:去重后的个数
top:出现频率最高的数
freq:出现的最高频率次数
user_info.describe(include=["object"])
统计下某列中每个值出现的次数 value_counts( )
调用 value_counts
方法快速获取 DataFrame 中每个值出现的次数。
user_info.sex.value_counts()
获取某列最大值或最小值对应的索引 idxmax( ) /idxmin()
可以使用 idxmax
或 idxmin
方法完成
user_info.age.idxmax()
c.自定义运算
apply(func, axis=0)
func:自定义函数;默认是列axis=0,对行进行运算axis=1。
示例:对’open’, ‘close’两列进行自定义运算
>>>data[['open', 'close']].apply(lambda x: x.max() - x.min(), axis=0)
===运行结果:======================================
open 22.74
close 22.85
dtype: float64
d.逻辑运算
data[data[ column_1 ]== french ]
data[(data[ column_1 ]== french ) & (data[ year_born ]1990)]
data[(data[ column_1 ] french ) & (data[ year_born ]1990) & ~(data[ city ] London )]
通过逻辑运算来取数据子集。要使用 & (AND)、 ~ (NOT) 和 | (OR),必须在逻辑运算前后加上「and」。
data[data[ column_1 ].isin([ french , english ])]
除了可以在同一列使用多个 OR,你还可以使用.isin() 函数。
apply(),applymap(),map()函数
在Python中如果想要对数据使用函数,可以借助apply(),applymap(),map() 来应用函数,括号里面可以是直接函数式,或者自定义函数(def)或者匿名函数(lambad)
import pandas as pd
import numpy as np
from pandas import DataFrame
from pandas import Series
df1= DataFrame({
"sales1":[-1,2,3],
"sales2":[3,-5,7],
})
df1
sales1 sales2
0 -1 3
1 2 -5
2 3 7
1、当我们要对数据框(DataFrame)的数据进行按行或按列操作时用apply()
df1.apply(lambda x :x.max()-x.min(),axis=1)
0 4
1 7
2 4
dtype: int64
df1.apply(lambda x :x.max()-x.min(),axis=0)
sales1 4
sales2 12
dtype: int64
关于axis参数的理解,请见我另一篇博客
2、当我们要对数据框(DataFrame)的每一个数据进行操作时用applymap(),返回结果是DataFrame格式
df1.applymap(lambda x : 1 if x>0 else 0)
sales1 sales2
0 0 1
1 1 0
2 1 1
3、当我们要对Series的每一个数据进行操作时用map()
df1["sales1"].map(lambda x : 1 if x>0 else 0)
0 0
1 1
2 1
Name: sales1, dtype: int64
补充:在处理大规模数据集时,pandas 会花费一些时间来进行.map()、.apply()、.applymap() 等操作。tqdm 是一个可以用来帮助预测这些操作的执行何时完成的包(是的,我说谎了,我之前说我们只会使用到 pandas)。
from tqdm import tqdm_notebook
tqdm_notebook().pandas()
用 pandas 设置 tqdm
data[ column_1 ].progress_map(lambda x: x.count( e ))
用 .progress_map() 代替.map()、.apply() 和.applymap() 也是类似的。在 Jupyter 中使用 tqdm 和 pandas 得到的进度条
tqdm会有另外的专题详细介绍,还没更新。
数据合并(concat,merge)
数据如下:
left = pd.DataFrame({'key1': ['K0', 'K0', 'K1', 'K2'],
'key2': ['K0', 'K1', 'K0', 'K1'],
'A': ['A0', 'A1', 'A2', 'A3'],
'B': ['B0', 'B1', 'B2', 'B3']})
right = pd.DataFrame({'key1': ['K0', 'K1', 'K1', 'K2'],
'key2': ['K0', 'K0', 'K0', 'K0'],
'C': ['C0', 'C1', 'C2', 'C3'],
'D': ['D0', 'D1', 'D2', 'D3']})
pd.concat实现数据合并
pd.concat([data1, data2], axis=1)
axis=0 跨行操作,行变列不变
axis=1 跨列操作,列变行不变
pd.concat([left,right],axis=1)
key1 key2 A B key1 key2 C D
0 K0 K0 A0 B0 K0 K0 C0 D0
1 K0 K1 A1 B1 K1 K0 C1 D1
2 K1 K0 A2 B2 K1 K0 C2 D2
3 K2 K1 A3 B3 K2 K0 C3 D3
pd.concat([left,right],axis=0)
key1 key2 A B C D
0 K0 K0 A0 B0 NaN NaN
1 K0 K1 A1 B1 NaN NaN
2 K1 K0 A2 B2 NaN NaN
3 K2 K1 A3 B3 NaN NaN
0 K0 K0 NaN NaN C0 D0
1 K1 K0 NaN NaN C1 D1
2 K1 K0 NaN NaN C2 D2
3 K2 K0 NaN NaN C3 D3
pd.merge实现数据合并
pd.merge(left, right, how='inner', on=None)
可以指定按照两组数据的共同键值对合并或者左右各自
left: DataFrame
right: 另一个DataFrame
on: 指定的共同键
how:按照什么方式连接
a.内连接
查询两个表中符合条件的共有记录
如图:
; b.外连接
两个表中所有记录都保留;两个表不存在的数据,使用np.NaN值填充。
c.左连接
以左表为主,根据条件查询右表数据;左表数据全部保留,右表不存在的数据,使用np.NaN值填充。
; d.右连接
以右表为主,根据条件查询左表数据;右表数据全部保留,左表不存在的数据,使用np.NaN值填充
分组和聚合
DataFrame.groupby(key, as_index=False)
key:分组的列数据,可以多个
案例:不同颜色的不同笔的价格数据
进行分组,对颜色分组,对价格进行聚合
>>>col =pd.DataFrame({'color': ['white','red','green','red','green'],
'object': ['pen','pencil','pencil','ashtray','pen'],
'price1':[5.56,4.20,1.30,0.56,2.75],
'price2':[4.75,4.12,1.60,0.75,3.15]})
color object price1 price2
0 white pen 5.56 4.75
1 red pencil 4.20 4.12
2 green pencil 1.30 1.60
3 red ashtray 0.56 0.75
4 green pen 2.75 3.15
颜色分组 价格聚合
>>>col.groupby(['color'])['price1'].mean()
color
green 2.025
red 2.380
white 5.560
Name: price1, dtype: float64
>>>col['price1'].groupby(col['color']).mean()
color
green 2.025
red 2.380
white 5.560
Name: price1, dtype: float64
添加参数as_index=False后,注意数据的结构的变化
>>>col.groupby(['color'], as_index=False)['price1'].mean()
color price1
0 green 2.025
1 red 2.380
2 white 5.560
agg()—- aggregation聚合函数 (没怎么用过)
dataset.groupby('color').agg([list])
交叉表与透视表(没怎么用过)
交叉表:用于计算一列数据对于另外一列数据的分组个数(用于统计分组频率的特殊透视表)
pd.crosstab(df["A"], df["B"])
透视表:透视表是将原有的DataFrame的列分别作为行索引和列索引,然后对指定的列应用聚集函数
dataframe.pivot_table([], index=[])
实操中遇到的问题及其解决办法
统计某列无重复的值
dataframe['列名'].unique()
统计指定列不重复的值的数目
方法一 duplicated
方法:
DataFrame.duplicated(subset = None,keep =‘first’ )返回boolean数组 一个bool值代表一行
参数:
subset:用来指定特定的列,默认所有列
keep:{‘first’,‘last’,False},默认’first’
first:标记重复,True除了第一次出现。
last:标记重复,True除了最后一次出现。
False:将所有重复项标记为True。
import pandas as pd
if __name__=="__main__":
path = "./test.csv"
df = pd.read_csv(path, header=0, names=["DEVICE_ID","LNG", "LAT","TEN_GROUP","WEEKDAY","FLOW"])
print("DEVICE_ID列不同值数目:\n%s\n\n" % str(len(df['DEVICE_ID'].unique())))
t=df.duplicated(subset=["DEVICE_ID"],keep=False)
print(t)
print(len(t[t==False]))
print("不重复键:")
print(df[~t])
DEVICE_ID列不同值数目:3
0 True
1 True
2 True
3 True
4 True
5 True
6 True
7 True
8 True
9 True
10 True
11 True
12 True
13 False
dtype: bool
1
不重复键:
DEVICE_ID LNG LAT TEN_GROUP WEEKDAY FLOW
13 3 123.0 43.0 102 1 29
方法二 value_counts()
df["DEVICE_ID"].value_counts()
遍历dataframe的每一行方法比较总结
数据初始化
import pandas as pd
import numpy as np
df = pd.DataFrame(np.random.randint(10, size=(1000000, 1)), columns=['num'])
下标遍历
(不建议使用)
for i in range(len(df)):
if df.iloc[i]['num'] < 5:
df.loc[i , 'num'] = 15
iterrows遍历
原理是将Dataframe迭代为Series,再返回结果。这一过程中需要进行类型检查,所以,会花费很长的时间。(不建议使用)
for index, row in df.iterrows():
if row['num'] < 5:
df.loc[index , 'num'] = 15
itertuples()
原理是将Dataframe迭代为tuple,再进行返回,由于元组不可变的特性,此过程不需要进行类型检查。(效率高,推荐使用)
for row in student.itertuples():
print(row.Index, row.name, row.account, row.pwd)
print(row.Index, getattr(row,'name'), getattr(row,'account'), getattr(row,'pwd'))
for + zip
这种方法是直接手动构造原生tuple,无需关心index数据。(效率高,推荐使用)
for A, B in zip(df['A'], df['B']):
print(A, B)
SettingWithCopyWarning警告
这段时间一直在用pandas,今天运行前人代码发现报了一个warning:
SettingWithCopyWarning: A value is trying to be set on a copy of a
slice from a DataFrame See the caveats in the documentation:
http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy
SettingWithCopyWarning出现的原因
链式赋值/Chained Assignment
SettingWithCopyWarning会在什么时候出现呢,简而言之就是在链式赋值的时候出现。
以下例子数据以此为例:
df1 = pd.DataFrame(np.random.random(20).reshape((10,2)), columns=list('AB'))
df1
什么是链式
链式就是进行多次同类型的操作,比如a = b = c = 4就是一个链式操作。在这里的链式操作主要是指,对于一个pandas格式的表,选取两次或者以上次数的其中结果。
比如选取其中A值小于0.3的行得到:
df1[df1.A < 0.3]
那么选取其中所有A
Original: https://blog.csdn.net/weixin_44217936/article/details/116700074
Author: 想躺平的小陈
Title: pandas中DataFrame各种方法总结(持续更新)
原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/750875/
转载文章受原作者版权保护。转载请注明原作者出处!