前言
-
本篇博客是我在Pandas官网的新手教程上学习时的学习笔记,少掉了关于pandas的绘图,主要是因为Matplotlib这个库我还没怎么学,等我这几两天学一学,有空了再来补这坑
-
pandas官网tutorials官方新手入门教程链接在这,学东西还是直接看官网文档快,就是看英文比较费时间。
Pandas基本操作
pandas用DataFrame来存储处理数据
A DataFrame is a 2-dimensional data structure that can store data of different types (including characters, integers, floating point values, categorical data and more) in columns. It is similar to a spreadsheet, a SQL table or the data.frame in R.
DataFrame中的每一列被称为一个Series。
- 可以直接创建一个系列,也可以在创建数据表的过程中创建系列
In [2]: df = pd.DataFrame(
...: {
...: "Name": [
...: "Braund, Mr. Owen Harris",
...: "Allen, Mr. William Henry",
...: "Bonnell, Miss. Elizabeth",
...: ],
...: "Age": [22, 35, 58],
...: "Sex": ["male", "male", "female"],
...: }
...: )
...:
In [3]: df
Out[3]:
Name Age Sex
0 Braund, Mr. Owen Harris 22 male
1 Allen, Mr. William Henry 35 male
2 Bonnell, Miss. Elizabeth 58 female
- 可以直接根据Serial的名称直接在一个DataFrame中取出一整个列的数据,可以理解为Python字典中的根据键直接取出值。
When selecting a single column of a pandas DataFrame, the result is a pandas Series. To select the column, use the column label in between square brackets [].
In [4]: df["Age"]
Out[4]:
0 22
1 35
2 58
Name: Age, dtype: int64
- 在DataFrame中Series是没有序号的(列标签),但是Series中的行数据是有标签的
A pandas Series has no column labels, as it is just a single column of a DataFrame. A Series does have row labels.
有了DataFrame和Series的概念后,我们就可以针对它们进行一些统计学的操作
- 得到系列中的最大值
In [7]: df["Age"].max() #通过在数据表中选择列
Out[7]: 58
In [8]: ages.max()
Out[8]: 58
- 可以数据表和系列的行数和列数进行查看,对数据表shape得到的是行数和列数,对系列shape只得到行数,因为系列只有一维,只能返回行数。同样shape也只是数据表和系列i的一个属性,不用带括号
titanic["Age"].shape
- 对数据表中的数值数据进行基本统计,以便快速了解数据
In [9]: df.describe()
Out[9]:
Age
count 3.000000
mean 38.333333
std 18.230012
min 22.000000
25% 28.500000
50% 35.000000
75% 46.500000
max 58.000000
- 如果想要获取数据表中的信息摘要,那么我们可以使用,数据表中内置方法.info()
In [9]: titanic.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 891 entries, 0 to 890
Data columns (total 12 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 PassengerId 891 non-null int64
1 Survived 891 non-null int64
2 Pclass 891 non-null int64
3 Name 891 non-null object
4 Sex 891 non-null object
5 Age 714 non-null float64
6 SibSp 891 non-null int64
7 Parch 891 non-null int64
8 Ticket 891 non-null object
9 Fare 891 non-null float64
10 Cabin 204 non-null object
11 Embarked 889 non-null object
dtypes: float64(2), int64(5), object(5)
memory usage: 83.7+ KB
实际上它也是一个数据表。数据表信息摘要中有:
- 使用.info()方法对象的类型,和Python中的type(data)方法返回结果类似
- 数据表中行数和行索引变化范围
- 数据表中的Series列数的数量
- 每一列数据的非空值和数据类型,
- 所有不同数据类型的总数
- 存储这个数据表大概需要多少内存空间。
对文件的读取操作
pandas可以从不同文件中读取数据,然后将其转换为DataFrame形式存储。其读取的方法就是在不同文件格式缩写前加上_read
前缀。
titanic = pd.read_csv(“data/titanic.csv”)
pandas provides the read_csv() function to read data stored as a csv file into a pandas DataFrame. pandas supports many different file formats or data sources out of the box (csv, excel, sql, json, parquet, …), each of them with the prefix read_*.
- 读取出来的数据默认是显示前五行和后五行,不对DataFrame使用任何方法而是直接打印就是这样的默认显示。如果我们需要有其他的显示要求,如光显示前几行,或者光显示后几行,就是需要好使用其自带的head() 和tail() 方法来指定了。
- 可以对数据表进行数据类型格式显示,使用 .dtypes即可 。
.dtype
是DataFrame或Series中的属性,而不是一个方法,所以并不需要括号。
不光可以从外部输入文件,pandas也可以将数据表转换为特定格式的文件导出,外部读入是read_* ,内部导出就是to_* 。如转换为电子表格,使用to_excel()即可,该方法会将数据表转换为.excel文件。此时再用read_excel()就又可以等效还原回来了
Whereas read_* functions are used to read data to pandas, the to_* methods are used to store data.
titanic.to_excel(“titanic.xlsx”, sheet_name=“passengers”, index=False)
#index= False 表示不会把数据表中的行索引数据保存在excel中
在数据表中选择子集
1. 在数据表中选择列(Series)
- 选择单个列,直接在方括号
[]
中填入对应的列表名称即可
In [4]: ages = titanic["Age"]
In [5]: ages.head()
Out[5]:
0 22.0
1 38.0
2 26.0
3 35.0
4 35.0
Name: Age, dtype: float64
- 要在数据表中选择多个列,就可以在方括号中填入包含多个列表名称的列表,即在方括号中的方括号,返回结果用DataFrame表示
age_sex = titanic[["Age", "Sex"]]
In [8]: age_sex = titanic[["Age", "Sex"]]
In [9]: age_sex.head()
Out[9]:
Age Sex
0 22.0 male
1 38.0 female
2 26.0 female
3 35.0 female
4 35.0 male
2. 在数据表中过滤出符合要求的行
- 可以直接在数据表的方括号中填写逻辑表达式,逻辑表达式会对数据表中的每一行进行检查,若符合条件即Ture,那么就会被过滤出来在新的数据表中。
In [12]: above_35 = titanic[titanic["Age"] > 35]
In [13]: above_35.head()
Out[13]:
PassengerId Survived Pclass ... Fare Cabin Embarked
1 2 1 1 ... 71.2833 C85 C
6 7 0 1 ... 51.8625 E46 S
11 12 1 1 ... 26.5500 C103 S
13 14 0 3 ... 31.2750 NaN S
15 16 1 2 ... 16.0000 NaN S
[5 rows x 12 columns]
- 直接输出逻辑表达式,我们可以得到一个和原先数据集同行数的数据表,其结果是对数据集的每一行都进行逻辑判断,返回该行的判断结果是Ture或False
In [14]: titanic["Age"] > 35
Out[14]:
0 False
1 True
2 False
3 False
4 False
...
886 False
887 False
888 False
889 False
890 False
Name: Age, Length: 891, dtype: bool
- 除了简单的逻辑表达式,还可以对每一行的数据进行数据范围的过滤。同样,用
isin()
对数据表进行过滤,返回的也是一个对数据表每一行进行isin
判断的Ture或False的数据表
In [16]: class_23 = titanic[titanic["Pclass"].isin([2, 3])]
In [17]: class_23.head()
Out[17]:
PassengerId Survived Pclass ... Fare Cabin Embarked
0 1 0 3 ... 7.2500 NaN S
2 3 1 3 ... 7.9250 NaN S
4 5 0 3 ... 8.0500 NaN S
5 6 0 3 ... 8.4583 NaN Q
7 8 0 3 ... 21.0750 NaN S
[5 rows x 12 columns]
- 上面的写法更为简洁,用逻辑表达式与或非也可以表示用样的意思,只不过不能概括,有点穷举法的意思
In [18]: class_23 = titanic[(titanic["Pclass"] == 2) | (titanic["Pclass"] == 3)]
In [19]: class_23.head()
Out[19]:
PassengerId Survived Pclass ... Fare Cabin Embarked
0 1 0 3 ... 7.2500 NaN S
2 3 1 3 ... 7.9250 NaN S
4 5 0 3 ... 8.0500 NaN S
5 6 0 3 ... 8.4583 NaN Q
7 8 0 3 ... 21.0750 NaN S
[5 rows x 12 columns]
- 此外,若有多个条件语句时,每一个条件语句都要用
()
括起来。而且,不能使用and
或or
来表示与或,而是要使用&
和|
来表示与或。
- 可以对某些列的值进行非空过滤,换句话说就是只想得到已知值的数据。对数据表使用
notna()
函数会为每一行返回一个布尔值,其会结合方括号中的指定内容来过滤数据表的非空数据。
In [20]: age_no_na = titanic[titanic["Age"].notna()]
In [21]: age_no_na.head()
Out[21]:
PassengerId Survived Pclass ... Fare Cabin Embarked
0 1 0 3 ... 7.2500 NaN S
1 2 1 1 ... 71.2833 C85 C
2 3 1 3 ... 7.9250 NaN S
3 4 1 1 ... 53.1000 C123 S
4 5 0 3 ... 8.0500 NaN S
[5 rows x 12 columns]
- 可能显示的依旧是数据表的前五行,我们可能看出不来是否变化,此时可以使用
shape
属性检查数据表的尺寸是否发生变化。
In [22]: age_no_na.shape
Out[22]: (714, 12)
3. 在数据表中选择出特定的行和列
- 前面提到的两种方法,都只能指定行或者列的条件,但其实我们还可以同时对这两者同时控制,此时进不能使用之前简单的方括号了,此时需要新的运算符
loc\iloc
。需要在方括号前加上loc\iloc
运算符,在方括号中,逗号前是我们选择的行,逗号后是我们选择的列
In this case, a subset of both rows and columns is made in one go and just using selection brackets [] is not sufficient anymore.
In [23]: adult_names = titanic.loc[titanic["Age"] > 35, "Name"]
In [24]: adult_names.head()
Out[24]:
1 Cumings, Mrs. John Bradley (Florence Briggs Th...
6 McCarthy, Mr. Timothy J
11 Bonnell, Miss. Elizabeth
13 Andersson, Mr. Anders Johan
15 Hewlett, Mrs. (Mary D Kingcome)
Name: Name, dtype: object
- 对于逗号前后的内容,可以使用很多形式,只要最终结果是对行的布尔值判定以及对列的选择即可。还可以使用
:
冒号,表示对行或者列从头到尾的选择。
For both the part before and after the comma, you can use a single label, a list of labels, a slice of labels, a conditional expression or a colon. Using a colon specifies you want to select all rows or columns.
- 我们可以对表格中的行和列的数值表示范围进行指定,此时需要使用到
iloc
运算符。与numpy中的索引切片类似,也可以用冒号来表示序列的切片
In [25]: titanic.iloc[9:25, 2:5]
Out[25]:
Pclass Name Sex
9 2 Nasser, Mrs. Nicholas (Adele Achem) female
10 3 Sandstrom, Miss. Marguerite Rut female
11 1 Bonnell, Miss. Elizabeth female
12 3 Saundercock, Mr. William Henry male
13 3 Andersson, Mr. Anders Johan male
.. ... ... ...
20 2 Fynney, Mr. Joseph J male
21 2 Beesley, Mr. Lawrence male
22 3 McGowan, Miss. Anna "Annie" female
23 1 Sloper, Mr. William Thompson male
24 3 Palsson, Miss. Torborg Danira female
[16 rows x 3 columns]
- 两个运算符之间的区别,
loc
是对数据表的行名和列名进行指定的,而iloc
是对数据表的中的特定位置坐标进行指定
Select specific rows and/or columns using loc when using the row and column names.
Select specific rows and/or columns using iloc when using the positions in the table.
- 可以使用这两个运算符对数据表进行条件筛选后,然后对被选择出来的行和列进行单独赋值。看我们是要用行列名或者用数据表中的数值索引来筛选,从而分别使用
loc
或者iloc
In [26]: titanic.iloc[0:3, 3] = "anonymous"
In [27]: titanic.head()
Out[27]:
PassengerId Survived Pclass ... Fare Cabin Embarked
0 1 0 3 ... 7.2500 NaN S
1 2 1 1 ... 71.2833 C85 C
2 3 1 3 ... 7.9250 NaN S
3 4 1 1 ... 53.1000 C123 S
4 5 0 3 ... 8.0500 NaN S
[5 rows x 12 columns]
4. 在数据表中从现有列中生成新的列
例题数据(空气质量数据)
In [2]: air_quality = pd.read_csv("data/air_quality_no2.csv", index_col=0, parse_dates=True)
In [3]: air_quality.head()
Out[3]:
station_antwerp station_paris station_london
datetime
2019-05-07 02:00:00 NaN NaN 23.0
2019-05-07 03:00:00 50.5 25.0 19.0
2019-05-07 04:00:00 45.0 27.7 19.0
2019-05-07 05:00:00 NaN 50.4 16.0
2019-05-07 06:00:00 NaN 61.9 NaN
- 直接在表达式等号左侧,数据表的方括号中写出想要新添加的列,然后在等号右侧写对原先的列的算术运算或逻辑运算,该运算会对给定列中的所有值都进行运算
In [4]: air_quality["london_mg_per_cubic"] = air_quality["station_london"] * 1.882
In [5]: air_quality.head()
Out[5]:
station_antwerp ... london_mg_per_cubic
datetime ...
2019-05-07 02:00:00 NaN ... 43.286
2019-05-07 03:00:00 50.5 ... 35.758
2019-05-07 04:00:00 45.0 ... 35.758
2019-05-07 05:00:00 NaN ... 30.112
2019-05-07 06:00:00 NaN ... NaN
[5 rows x 4 columns]
Also other mathematical operators (
+
,-
,*
,/
,…) or logical operators (<
,>
,==
,…) work element-wise.
- 想要进行更复杂的运算,就需要用到数据表的 apply() 方法了
- 除了手动创建新的列,我们还可以对已存在的列进行重命名.rename()函数可用于行标签和列标签。提供一个字典,其中包含当前名称的键和新名称的值以更新相应的名称。
In [8]: air_quality_renamed = air_quality.rename(
columns={
"station_antwerp": "BETR801",
"station_paris": "FR04014",
"station_london": "London Westminster",
}
)
In [9]: air_quality_renamed.head()
Out[9]:
BETR801 FR04014 ... london_mg_per_cubic ratio_paris_antwerp
datetime ...
2019-05-07 02:00:00 NaN NaN ... 43.286 NaN
2019-05-07 03:00:00 50.5 25.0 ... 35.758 0.495050
2019-05-07 04:00:00 45.0 27.7 ... 35.758 0.615556
2019-05-07 05:00:00 NaN 50.4 ... 30.112 NaN
2019-05-07 06:00:00 NaN 61.9 ... NaN NaN
[5 rows x 5 columns]
对数据表的聚合统计
- 我们可以直接对单列数据进行平均值的统计,但要是统计多列的平均值呢?首先我们需要对多个目标列用列表
[]
括起来进行聚合,和之前提到的在数据表中选择多个列操作一样,然后再对这多个列进行统计平均值操作。
In [5]: titanic[["Age", "Fare"]].median()
Out[5]:
Age 28.0000
Fare 14.4542
dtype: float64
- 同样对于之前的describe()数据表数据概述,也可以应用到多个列上
In [6]: titanic[["Age", "Fare"]].describe()
Out[6]:
Age Fare
count 714.000000 891.000000
mean 29.699118 32.204208
std 14.526497 49.693429
min 0.420000 0.000000
25% 20.125000 7.910400
50% 28.000000 14.454200
75% 38.000000 31.000000
max 80.000000 512.329200
- 但是我们也可以自定义想要显示的统计信息的特定组合,而不是像describe()中预定义好的统计信息,使用
DataFrame.agg()
在参数列表内填入字典,字典中的键值对是目标列以及想要显示的统计信息(有多个就用列表表示 )
In [7]: titanic.agg(
...: {
...: "Age": ["min", "max", "median", "skew"],
...: "Fare": ["min", "max", "median", "mean"],
...: }
...: )
...:
Out[7]:
Age Fare
min 0.420000 0.000000
max 80.000000 512.329200
median 28.000000 14.454200
skew 0.389108 NaN
mean NaN 32.204208
对数据表的分组统计
- 可以对统计信息进行类别分组
和数据库条件查询操作类似,这边做的信息统计是列中的每一个类别分组进行的,使用groupby()
可以对指定列的每一个类别进行分组,然后对数据表的统计操作就会单独作用于每一个分组,最后这些结果会被合成一个数据表
the groupby() method is applied on the Sex column to make a group per category.
In [8]: titanic[["Sex", "Age"]].groupby("Sex").mean()
Out[8]:
Age
Sex
female 27.915709
male 30.726645
-
只是单独对数据表进行分类没有什么意义,分组后要跟上对数据的操作,这样才能实现更灵活的运算。
-
上面的例子是事先选择了两列,若没有提前选择列,那么就会默认全部列, 这边利用
numeric_only =True
指定平均值计算只应用于数值类数据
In [9]: titanic.groupby("Sex").mean(numeric_only=True)
Out[9]:
PassengerId Survived Pclass ... SibSp Parch Fare
Sex ...
female 431.028662 0.742038 2.159236 ... 0.694268 0.649682 44.479818
male 454.147314 0.188908 2.389948 ... 0.429809 0.235702 25.523893
[2 rows x 7 columns]
- 上面的例子是先选择列后分组,但我们也可以先分组再选择
In [10]: titanic.groupby("Sex")["Age"].mean()
Out[10]:
Sex
female 27.915709
male 30.726645
Name: Age, dtype: float64
- 不止可以对一个列进行分组,也可以对多个列进行分类,将多个列用列表存储起来就行了。这样分组的结果就是所有类别的排列组合(树形),然后类别的排列顺序依靠分组函数参数列表中列名的先后顺序
In [11]: titanic.groupby(["Sex", "Pclass"])["Fare"].mean()
Out[11]:
Sex Pclass
female 1 106.125798
2 21.970121
3 16.118810
male 1 67.226127
2 19.741782
3 12.661633
Name: Fare, dtype: float64
- 可以按分组计算记录数
如想要查看每个舱位等级的乘客人数是多少,value_counts()方法计算列中每个类别的记录数。在该方法中,可以利用该方法的参数dropna
来包含或者排除缺失值。
In [12]: titanic["Pclass"].value_counts()
Out[12]:
3 491
1 216
2 184
Name: Pclass, dtype: int64
- 利用上面提到的分组操作也可以实现计数功能,只不过功能没有
value_count()
来得灵活方便
Both size and count can be used in combination with groupby. Whereas size includes NaN values and just provides the number of rows (size of the table), count excludes the missing values. In the value_counts method, use the dropna argument to include or exclude the NaN values.
In [13]: titanic.groupby("Pclass")["Pclass"].count()
Out[13]:
Pclass
1 216
2 184
3 491
Name: Pclass, dtype: int64
重塑表格布局
对表格进行排序
可以使用sort_values(),数据表中的行会根据指定的列进行排序,其中by=
是排序的依据,默认是升序排序
In [6]: titanic.sort_values(by="Age").head()
Out[6]:
PassengerId Survived Pclass ... Fare Cabin Embarked
803 804 1 3 ... 8.5167 NaN C
755 756 1 2 ... 14.5000 NaN S
644 645 1 3 ... 19.2583 NaN C
469 470 1 3 ... 19.2583 NaN C
78 79 1 2 ... 29.0000 NaN S
[5 rows x 12 columns]
- 可以同时对多个列进行排序,同时还可以选择降序排序,对参数进行调整
ascending=False
In [7]: titanic.sort_values(by=['Pclass', 'Age'], ascending=False).head()
Out[7]:
PassengerId Survived Pclass ... Fare Cabin Embarked
851 852 0 3 ... 7.7750 NaN S
116 117 0 3 ... 7.7500 NaN Q
280 281 0 3 ... 7.7500 NaN Q
483 484 1 3 ... 9.5875 NaN S
326 327 0 3 ... 6.2375 NaN S
[5 rows x 12 columns]
合并多个表的数据
1. 按行或列连接表
- 利用
concat()
函数沿其中一个轴(按行或按列)执行多个表的串联操作,也就是说我们进左右合并或者上下合并。数据表有两个轴,axis=0
代表垂直方向合并行,axis=1
代表水平方向上合并列。串联默认是沿着axis=0
进行的。
In [8]: air_quality = pd.concat([air_quality_pm25, air_quality_no2], axis=0)
In [9]: air_quality.head()
Out[9]:
date.utc location parameter value
0 2019-06-18 06:00:00+00:00 BETR801 pm25 18.0
1 2019-06-17 08:00:00+00:00 BETR801 pm25 6.5
2 2019-06-17 07:00:00+00:00 BETR801 pm25 18.5
3 2019-06-17 06:00:00+00:00 BETR801 pm25 16.0
4 2019-06-17 05:00:00+00:00 BETR801 pm25 7.5
- 在这个例子数据当中,两个表是都各自的参数
parameter
可以标记数据原先所属,但不一定每一次合并的数据表中都有自己的标记。 - 我们可以使用
concat()
中的函数参数keys
来添加一个额外的行索引来标记不同的原始表
In this specific example, the parameter column provided by the data ensures that each of the original tables can be identified. This is not always the case. The concat function provides a convenient solution with the keys argument, adding an additional (hierarchical) row index.
In [15]: air_quality_ = pd.concat([air_quality_pm25, air_quality_no2], keys=["PM25", "NO2"])
In [16]: air_quality_.head()
Out[16]:
date.utc location parameter value
PM25 0 2019-06-18 06:00:00+00:00 BETR801 pm25 18.0
1 2019-06-17 08:00:00+00:00 BETR801 pm25 6.5
2 2019-06-17 07:00:00+00:00 BETR801 pm25 18.5
3 2019-06-17 06:00:00+00:00 BETR801 pm25 16.0
4 2019-06-17 05:00:00+00:00 BETR801 pm25 7.5
2. 通过公共列连接表
- 通过共同键从而将两个表连接在一起,类似数据库中的表连接概念,
how=left
说明是左连接方式,即参数列表中左边一个数据表中每行每列都会在新表上显示出来,on="location"
就是我们指定的要连接的公共键
In [20]: air_quality = pd.merge(air_quality, stations_coord, how="left", on="location")
In [21]: air_quality.head()
Out[21]:
date.utc ... coordinates.longitude
0 2019-05-07 01:00:00+00:00 ... -0.13193
1 2019-05-07 01:00:00+00:00 ... 2.39390
2 2019-05-07 01:00:00+00:00 ... 2.39390
3 2019-05-07 01:00:00+00:00 ... 4.43182
4 2019-05-07 01:00:00+00:00 ... 4.43182
[5 rows x 6 columns]
- 上面的例子是在对两个表的同名列进行来连接,但我们也可以对两个表的不同名列进行连接,在参数
left_on
和right_on
中指定即可
In [24]: air_quality = pd.merge(air_quality, air_quality_parameters,
....: how='left', left_on='parameter', right_on='id')
....:
In [25]: air_quality.head()
Out[25]:
date.utc ... name
0 2019-05-07 01:00:00+00:00 ... NO2
1 2019-05-07 01:00:00+00:00 ... NO2
2 2019-05-07 01:00:00+00:00 ... NO2
3 2019-05-07 01:00:00+00:00 ... PM2.5
4 2019-05-07 01:00:00+00:00 ... NO2
[5 rows x 9 columns]
- 除了左连接外,pandas还支持内连接、外连接和全连接等
pandas supports also inner, outer, and right joins. More information on join/merge of tables is provided in the user guide section on database style merging of tables. Or have a look at the comparison with SQL page.
对时间序列数据进行处理
- 有时我们的日期是用字符串存储的,pandas中提供了
to_datatime
方法可以将标准时间戳转换为Timestamp对象,这样日期就由字符串变换为数字了,转换后的数据类型为pandas.Timestamp.
In [7]: air_quality["datetime"] = pd.to_datetime(air_quality["datetime"])
In [8]: air_quality["datetime"]
Out[8]:
0 2019-06-21 00:00:00+00:00
1 2019-06-20 23:00:00+00:00
2 2019-06-20 22:00:00+00:00
3 2019-06-20 21:00:00+00:00
4 2019-06-20 20:00:00+00:00
...
2063 2019-05-07 06:00:00+00:00
2064 2019-05-07 04:00:00+00:00
2065 2019-05-07 03:00:00+00:00
2066 2019-05-07 02:00:00+00:00
2067 2019-05-07 01:00:00+00:00
Name: datetime, Length: 2068, dtype: datetime64[ns, UTC]
- 同样在很多文件时,里面的日期数据也是用字符串存储的,在导入文件时可以使用参数
parse_dates
将其转换为日期对象
pd.read_csv("../data/air_quality_no2_long.csv", parse_dates=["datetime"])
- 有了日期信息后,我们就可以在pandas.Timestamp中使用一些方法来对日期进行操作了
In [9]: air_quality["datetime"].min(), air_quality["datetime"].max()
Out[9]:
(Timestamp('2019-05-07 01:00:00+0000', tz='UTC'),
Timestamp('2019-06-21 00:00:00+0000', tz='UTC'))
- 甚至我们可以得出数据表中的时间跨度,用最大时间减去最小时间即可
In [10]: air_quality["datetime"].max() - air_quality["datetime"].min()
Out[10]: Timedelta('44 days 23:00:00')
- 可以从Timestamp对象中,取出很多与时间相关的属性,例如
year
,weekofyear
,quarter
等属性,通过.dt
访问器就可以从时间戳对象中去这些属性,.dt
访问器返回的是一个Series,
In [11]: air_quality["month"] = air_quality["datetime"].dt.month
In [12]: air_quality.head()
Out[12]:
city country datetime ... value unit month
0 Paris FR 2019-06-21 00:00:00+00:00 ... 20.0 µg/m³ 6
1 Paris FR 2019-06-20 23:00:00+00:00 ... 21.8 µg/m³ 6
2 Paris FR 2019-06-20 22:00:00+00:00 ... 26.5 µg/m³ 6
3 Paris FR 2019-06-20 21:00:00+00:00 ... 24.9 µg/m³ 6
4 Paris FR 2019-06-20 20:00:00+00:00 ... 21.4 µg/m³ 6
[5 rows x 8 columns]
转换时间序列的频率
- 这个操作类似于之前的分组操作,也是需要配合聚合函数一起操作才行,如我们想要获取每个月日期的最大值,也就是最后一天月尾,就可以使用
reshape("M")
,除了这个我们还有其他类似的概述名可供选择 offset aliases overview table
In [22]: monthly_max = no_2.resample("M").max()
In [23]: monthly_max
Out[23]:
location BETR801 FR04014 London Westminster
datetime
2019-05-31 00:00:00+00:00 74.5 97.0 97.0
2019-06-30 00:00:00+00:00 52.5 84.7 52.0
对文本数据的操作
pandas中提供了str
访问器,使用该访问器,可以让我们对字符串数据进行专门的字符串操作。
1. 将字符串转为小写
将所有字符串都设为小写
In [4]: titanic["Name"].str.lower()
Out[4]:
0 braund, mr. owen harris
1 cumings, mrs. john bradley (florence briggs th...
2 heikkinen, miss. laina
3 futrelle, mrs. jacques heath (lily may peel)
4 allen, mr. william henry
...
886 montvila, rev. juozas
887 graham, miss. margaret edith
888 johnston, miss. catherine helen "carrie"
889 behr, mr. karl howell
890 dooley, mr. patrick
Name: Name, Length: 891, dtype: object
2. 分隔字符串
指定分隔符将原本的字符串分隔开,分隔后的字符用列表存储起来,返回的是被分隔元素列表
In [5]: titanic["Name"].str.split(",")
Out[5]:
0 [Braund, Mr. Owen Harris]
1 [Cumings, Mrs. John Bradley (Florence Briggs ...
2 [Heikkinen, Miss. Laina]
3 [Futrelle, Mrs. Jacques Heath (Lily May Peel)]
4 [Allen, Mr. William Henry]
...
886 [Montvila, Rev. Juozas]
887 [Graham, Miss. Margaret Edith]
888 [Johnston, Miss. Catherine Helen "Carrie"]
889 [Behr, Mr. Karl Howell]
890 [Dooley, Mr. Patrick]
Name: Name, Length: 891, dtype: object
- 此外,我们还可以对分隔后的部分进行选择,Series.str.get()即可对字符串进行选择,这边将分隔操作和部分选择操作组合了在一起
In [6]: titanic["Surname"] = titanic["Name"].str.split(",").str.get(0)
# 选择了第一部分
In [7]: titanic["Surname"]
Out[7]:
0 Braund
1 Cumings
2 Heikkinen
3 Futrelle
4 Allen
...
886 Montvila
887 Graham
888 Johnston
889 Behr
890 Dooley
Name: Surname, Length: 891, dtype: object
3. 查找含有特定文本的行
查找数据表中符合给定名称的项,使用字符串访问器的contains()
方法,这个方法可以对给定表的所有行进行逻辑判定,会给每一行数据都返回一个布尔值。该方法支持正则表达式,可以进行更强大的文本提取方法。
In [8]: titanic["Name"].str.contains("Countess")
Out[8]:
0 False
1 False
2 False
3 False
4 False
...
886 False
887 False
888 False
889 False
890 False
Name: Name, Length: 891, dtype: bool
- 有了这个布尔值,我们就可以对给定数据表进行条件查询。只有被筛选为True的行才会被选择出来。
In [9]: titanic[titanic["Name"].str.contains("Countess")]
Out[9]:
PassengerId Survived Pclass ... Cabin Embarked Surname
759 760 1 1 ... B77 S Rothes
[1 rows x 13 columns]
4. 计算字符串长度
使用访问其中的len()
就能得到被访问对象的字符串长度
In [10]: titanic["Name"].str.len()
Out[10]:
0 23
1 51
2 22
3 44
4 24
..
886 21
887 28
888 40
889 21
890 19
Name: Name, Length: 891, dtype: int64
除了得到字串的长度外,我们还可以找到最长字符所在行的索引值,使用访问器中的方法idxmax()
,可以返回给定的数据列表中最大值所在行的索引值
In [11]: titanic["Name"].str.len().idxmax()
Out[11]: 307
5。替换字符
使用replace()
,将旧字符和新字符用键值对的方式存储在字典中,然后将字典存放在方法的参数列表中,
In [13]: titanic["Sex_short"] = titanic["Sex"].replace({"male": "M", "female": "F"})
In [14]: titanic["Sex_short"]
Out[14]:
0 M
1 F
2 F
3 F
4 M
..
886 M
887 F
888 F
889 M
890 M
Name: Sex_short, Length: 891, dtype: object