pandas的常用数据类型
1. Series一维,带标签数组
2. DataFrame二维,Series容器
pandas之Series创建
In [15]: a = {string.ascii_uppercase[i]:i for i in range(10)}
# 字典推导式创建一个字典a
In [16]: a
Out[16]:
{'A': 0,
'B': 1,
'C': 2,
'D': 3,
'E': 4,
'F': 5,
'G': 6,
'H': 7,
'I': 8,
'J': 9}
In [17]: pd.Series(a)
# 通过字典创建一个Series,注意其中的索引就是字典的键
Out[17]:
A 0
B 1
C 2
D 3
E 4
F 5
G 6
H 7
I 8
J 9
dtype: int64
In [18]: pd.Series(a, index=list(string.ascii_uppercase[5:15]))
# 重新给其指定其他索引之后,如果能够对应上,就取其值,如果不能就Nan
Out[18]:
F 5.0
G 6.0
H 7.0
I 8.0
J 9.0
K NaN
L NaN
M NaN
N NaN
O NaN
dtype: float64
# pandas会自动根据数据类型更改series的dtype类型
pandas之读取外部数据
我们的这组数据存在csv中,我们直接使用pd.read_csv即可
和我们想象的有些差别,我们以为他会是一个Series类型,但是他是一个DataFrame。
对于数据库比如mysql或者mongodb中的数据我们如何使用呢?
pd.read_sql(sql_sentence, connection)
pandas之DataFrame
In [4]: t = pd.DataFrame(np.arange(12).reshape((3, 4)))
In [5]: t
Out[5]:
0 1 2 3
0 0 1 2 3
1 4 5 6 7
2 8 9 10 11
DataFrame对象既有行索引,又有列索引
行索引,表明不同行,横向索引,叫index,0轴,axis=0
列索引,表名不同列,纵向索引,叫columns,1轴,axis=1
pandas之DataFrame
和一个ndarray一样,我们通过shape,ndim,dtype了解这个ndarray的基本信息,那么对于DataFrame我们有什么方法了解呢
DataFrame基础属性
df.shape # 行数 列数
df.dtypes # 列数据类型
df.nidm # 数据维度
df.index # 行索引
df.columns # 列索引
df.values # 对象值,二维ndarry数组
DataFrame整体情况查询
df.head(3) # 显示头部几行,默认5行
df.tail(3) # 显示末尾几行,默认5行
df.info() # 相关信息概览:行数,列数,列索引,列非空值个数,列类型,内存占用
df.describe() # 快速综合统计结果:计数,均值,标准差,最大值,四分位数,最小值
df.sort_values(by="Count_AnimalName", ascending=False)
# 按照“Count_AnimalName”列降序排列
pandas之loc
- df.loc 通过标签索引行数据
- df.iloc 通过位置获取行索引
In [28]: df
Out[28]:
W X Y Z
A 0 1 2 3
B 4 5 6 7
C 8 9 10 11
In [29]: df.loc["A", "W"]
Out[29]: 0
In [30]: df.loc["A", ["W", "Z"]]
Out[30]:
W 0
Z 3
Name: A, dtype: int32
In [31]: type(df.loc["A", ["W", "Z"]])
Out[31]: pandas.core.series.Series
# 选择间隔的多行
In [32]: df.loc[["A", "C"], ["W", "Z"]]
Out[32]:
W Z
A 0 3
C 8 11
In [33]: df.loc["A":, ["W", "Z"]]
Out[33]:
W Z
A 0 3
B 4 7
C 8 11
# 冒号在loc里面是闭合的,即会选择到冒号后面的数据
In [34]: df.loc["A":"C", ["W", "Z"]]
Out[34]:
W Z
A 0 3
B 4 7
C 8 11
缺失数据的处理
对于NaN的数据,在numpy中我们是如何处理的?
在pandas中我们处理起来非常容易
判断数据是否为NaN:pd.isnull(df), pd.notnull(df)
处理方式1:删除NaN所在的行列dripna(axis=0, how='any', inplace=False)
处理方式2:填充数据,t.fillna(t.mean()), t.fillna(t.median()), t.fillna(0)
处理为0的数据:t[t==0]=np.nan
当然并不是每次为0的数据都需要处理
计算平均值等情况,nan是不参加计算的,但是0会
pandas常用统计方法
# 评分的平均分
rating_mean = df["Rating"].mean()
# 导演的人数
temp_list = df["Actors"].str.split(",").tolist()
nums = set([i for j in temp_list for i in j])
# 电影时长的最大值
max_runtime = df["Runtime (Minutes)"].max()
max_runtime_index = df["Runtime (Minutes)"].argmax()
min_runtime = df["Runtime (Minutes)"].argmin()
runtime_median = df["Runtime (Minutes)"].median()
数据合并之join
In [6]: t1
Out[6]:
M N X Y
A 0.0 0.0 0.0 0.0
B 0.0 0.0 0.0 0.0
In [7]: t2
Out[7]:
1 2 3
A 1.0 1.0 1.0
B 1.0 1.0 1.0
C 1.0 1.0 1.0
In [8]: t2.join(t1)
Out[8]:
1 2 3 M N X Y
A 1.0 1.0 1.0 0.0 0.0 0.0 0.0
B 1.0 1.0 1.0 0.0 0.0 0.0 0.0
C 1.0 1.0 1.0 NaN NaN NaN NaN
In [9]: t1.join(t2)
Out[9]:
M N X Y 1 2 3
A 0.0 0.0 0.0 0.0 1.0 1.0 1.0
B 0.0 0.0 0.0 0.0 1.0 1.0 1.0
数据合并之merge
merge:按照指定的列把数据按照一定的方式合并到一起
In [75]: t1
Out[75]:
M N O P
A 1.0 1.0 a 1.0
B 1.0 1.0 b 1.0
C 1.0 1.0 c 1.0
In [76]: t2
Out[76]:
V W X Y Z
A 0.0 0.0 c 0.0 0.0
B 0.0 0.0 d 0.0 0.0
In [77]: t1.merge(t2, left_on="O", right_on="X")
Out[77]:
M N O P V W X Y Z
0 1.0 1.0 c 1.0 0.0 0.0 c 0.0 0.0
In [78]: t1.merge(t2, left_on="O", right_on="X", how="inner")
Out[78]:
M N O P V W X Y Z
0 1.0 1.0 c 1.0 0.0 0.0 c 0.0 0.0
In [79]: t1.merge(t2, left_on="O", right_on="X", how="outer")
Out[79]:
M N O P V W X Y Z
0 1.0 1.0 a 1.0 NaN NaN NaN NaN NaN
1 1.0 1.0 b 1.0 NaN NaN NaN NaN NaN
2 1.0 1.0 c 1.0 0.0 0.0 c 0.0 0.0
3 NaN NaN NaN NaN 0.0 0.0 d 0.0 0.0
In [80]: t1.merge(t2, left_on="O", right_on="X", how="left")
Out[80]:
M N O P V W X Y Z
0 1.0 1.0 a 1.0 NaN NaN NaN NaN NaN
1 1.0 1.0 b 1.0 NaN NaN NaN NaN NaN
2 1.0 1.0 c 1.0 0.0 0.0 c 0.0 0.0
In [81]: t1.merge(t2, left_on="O", right_on="X", how="right")
Out[81]:
M N O P V W X Y Z
0 1.0 1.0 c 1.0 0.0 0.0 c 0.0 0.0
1 NaN NaN NaN NaN 0.0 0.0 d 0.0 0.0
数据分组聚合
grouped = df.groupby(by="columns name")
grouped是一个DataFrameGroupBy对象,是可迭代的
grouped中的每一个元素是一个元组
元组里面是(索引(分组的值),分组之后的DataFrame)
DataFrameGroupBy对象有很多经过优化的方法
函数名 | 说明 |
---|---|
count | 分组中非NA值的数量 |
sum | 非NA值的和 |
mean | 非NA值的平均值 |
median | 非NA值的算术中位数 |
std、var | 无偏(分母为n-1)标准差和方差 |
min、max | 非NA的最小值和最大值 |
如果我们需要对国家和省份进行分组统计,应该怎么操作呢? | |
grouped = df.groupby(by=[df["Country"], df["State/Province"]]) |
获取分组之后的某一部分数据:
df.groupby(by=["Country", "State/Province"])["Country"].count()
对某几列进行分组:
df["Country"].groupby(by=[df["Country"], df["State/Province"]]).count()
观察结果,由于只选择了一列数据,所以结果是一个Series类型如果想返回一个DataFrame类型:
df[["Country"]].groupby(by=[df["Country"], df["State/Province"]]).count()
索引和复合索引
简单的索引操作:
- 获取index:df.index
- 指定index:df.index = ['x, y']
- 重新设置index:df.reindex(list("abcdef"))
- 指定某一列作为index:df.set_index("Country", drop=False)
- 返回index的唯一值:df.set_index("Country").index.unique()
pandas时间序列
生成一段时间范围
pd.date_range(start=None, end=None, periods=None, freq='D')
start和end以及freq配合能够生成start和end范围内以频率freq的一组时间索引
start和periods以及freq配合能够生成从start开始的频率为freq的periods个时间索引
In [23]: pd.date_range(start='20170101', end='20180101')
Out[23]:
DatetimeIndex(['2017-01-01', '2017-01-02', '2017-01-03', '2017-01-04',
'2017-01-05', '2017-01-06', '2017-01-07', '2017-01-08',
'2017-01-09', '2017-01-10',
...
'2017-12-23', '2017-12-24', '2017-12-25', '2017-12-26',
'2017-12-27', '2017-12-28', '2017-12-29', '2017-12-30',
'2017-12-31', '2018-01-01'],
dtype='datetime64[ns]', length=366, freq='D')
In [24]: pd.date_range(start='20170101', end='20180101', freq='BM')
Out[24]:
DatetimeIndex(['2017-01-31', '2017-02-28', '2017-03-31', '2017-04-28',
'2017-05-31', '2017-06-30', '2017-07-31', '2017-08-31',
'2017-09-29', '2017-10-31', '2017-11-30', '2017-12-29'],
dtype='datetime64[ns]', freq='BM')
In [25]: pd.date_range(start='20170101', end='20180101', freq='WOM-3FRI')
Out[25]:
DatetimeIndex(['2017-01-20', '2017-02-17', '2017-03-17', '2017-04-21',
'2017-05-19', '2017-06-16', '2017-07-21', '2017-08-18',
'2017-09-15', '2017-10-20', '2017-11-17', '2017-12-15'],
dtype='datetime64[ns]', freq='WOM-3FRI')
关于频率的更多缩写
别名 | 偏移量类型 | 说明 |
---|---|---|
D | Day | 每日历日 |
B | BusinessDay | 每工作日 |
H | Hour | 每小时 |
T或min | Minute | 每分 |
S | Second | 每秒 |
L | ms | Milli |
U | Micro | 每微秒 |
M | MonthEnd | 每月最后一个日历日 |
BM | BusinessMonthEnd | 每月最后一个工作日 |
MS | MonthBegin | 每月第一个日历日 |
BMS | BusinessMonthBegin | 每月第一个工作日 |
使用pandas提供的方法把时间字符串转化为时间序列
df["timeStamp"] = pd.to_datetime(df["timeStamp"], format="")
format参数大部分情况下可以不用写,但是对于pandas无法格式化的时间字符串,我们可以使用该参数,比如包含中文
pandas重采样
重采样:指的是将时间序列从一个频率转化为另一个频率进行处理的过程,将高频率数据转化为低频率数据为降采样,低频率转化为高频率为升采样
pandas提供了一个resample的方法来帮助我们实现频率转化
In [78]: t = pd.DataFrame(np.random.uniform(10, 50, (100, 1)), index=pd.date_range(start="20170101", periods=100))
In [80]: t.resample("M").mean()
Out[80]:
0
2017-01-31 28.025613
2017-02-28 30.814253
2017-03-31 33.023321
2017-04-30 27.950424
In [81]: t.resample("QS-JAN").count()
Out[81]:
0
2017-01-01 90
2017-04-01 10