Python-pandas 笔记整理

个人笔记整理,仅供自学使用
Reference:
https://vitu.ai/course/65599145397748608
https://vitu.ai/course/65598890065315648

导包

import pandas as pd

创建与读写

创建数据

pandas中有两个核心对象:DataFrame和Series。
DataFrame是一个表。 它包含一系列单独的条目,每个条目都有一定的值。 每个条目对应一行(或记录)和一列。
例如,请考虑以下简单的DataFrame:

pd.DataFrame({'Yes': [50, 21], 'No': [131, 2]})
Yes No
0 50 131
1 21 2

在此示例中,“0,No”条目的值为131.“0,Yes”条目的值为50,依此类推。
DataFrame条目不限于整数,字符串也可以。

我们使用pd.DataFrame构造函数来生成这些DataFrame对象。创建新对象的语法是初始化一个字典,其键是列名(本例中为Bob和Sue),其值是条目列表。 这是构建新DataFrame的标准方法,也是你最容易遇到的方法。
字典列表的构造函数为列标签分配值,但只使用0(0,1,2,3,…)的递增计数作为行标签。 有时候这没关系,但我们经常会想要自己分配这些行标签。
DataFrame中使用的行标签列表称为索引。 我们可以在构造函数中使用索引参数为其赋值:

pd.DataFrame({'Bob': ['I liked it.', 'It was awful.'], 
              'Sue': ['Pretty good.', 'Bland.']},
             index=['Product A', 'Product B'])

Python-pandas 笔记整理_第1张图片
相比之下,Series是一系列数据值。 如果DataFrame是表,则Series是列表。 事实上,你可以创建一个Series只有一个列表:

pd.Series([1, 2, 3, 4, 5])
0    1
1    2
2    3
3    4
4    5
dtype: int64

Series本质上是DataFrame的单个列。 因此,你可以使用索引参数以与之前相同的方式为Series分配列值。 但是,Series没有列名,它只有一个总名称:

pd.Series([30, 35, 40], index=['2015 Sales', '2016 Sales', '2017 Sales'], name='Product A')
2015 Sales    30
2016 Sales    35
2017 Sales    40
Name: Product A, dtype: int64

Series还可以从字典(dict)创建:

d = {'a': 0., 'b': 1, 'c': 2}
print("d is a dict:")
print(d)
s = Series(d)
print("s is a Series:")
print(s)
d is a dict:
{'a': 0.0, 'b': 1, 'c': 2}
s is a Series:
a    0.0
b    1.0
c    2.0
dtype: float64

我们可以观察到两点:一是字典创建的Series,数据将按index的顺序重新排列;二是index长度可以和字典长度不一致,如果多了的话,pandas将自动为多余的index分配NaN(not a number,pandas中数据缺失的标准记号),当然index少的话就截取部分的字典内容。

如果数据就是一个单一的变量,如数字4,那么Series将重复这个变量:

Series(4., index=['a', 'b', 'c', 'd', 'e'])
a    4.0
b    4.0
c    4.0
d    4.0
e    4.0
dtype: float64

Series和DataFrame密切相关。 将DataFrame视为实际上只是一堆Series“粘合在一起”是有帮助的。

读常用文件csv

能够手动创建DataFrame和Series非常方便。 但是,在大多数情况下,我们实际上不会手动创建自己的数据,我们将使用已经存在的数据。

数据可以以多种不同的形式和格式存储。 到目前为止,其中最基本的是简单的CSV文件。 当你打开CSV文件时,会看到如下所示的内容:
csv
Product A,Product B,Product C,
30,21,9,
35,34,1,
41,11,11

CSV文件是由逗号分隔的表,现在让我们把我们的玩具数据集放在一边,看看当我们将它读入DataFrame时真正的数据集是什么样的。
点击这里 下载 数据集

melbourne_data = pd.read_csv('melb_data.csv') 

使用shape属性来检查生成的DataFrame的大小:

melbourne_data.shape
(13580, 21)

因此,我们的新DataFrame有1万3千多条记录,分为21个不同的列。
我们可以使用head命令检查结果DataFrame的内容,该命令抓取前五行:

melbourne_data.head()
#读取尾部后三条
print(melbourne_data.tail(3))

pandas read_csv函数功能丰富,可以指定30多个可选参数。 例如,你可以在创建数据集时候使用csv文件某列作为内置索引,而pandas默认不会自动获取。 为了使pandas将该列用于索引(而不是从头开始创建新索引),我们可以指定并使用index_col。

#指定某列为索引列
melbourne_data = pd.read_csv('melb_data.csv', index_col=0)
melbourne_data.head()

读常用文件excel

Excel文件(XLS或XLST)将自身组织为一系列命名工作表。 每张Sheet基本上都是一张表格。 因此,要将数据加载到pandas中,我们需要一个额外的参数:感兴趣的工作表的名称。

wic = pd.read_excel("WICAgencies2013ytd.xls", 
                    sheet_name='Total Women')
wic.head()

正如你在此示例中所看到的,Excel文件通常不像CSV文件那样格式化。电子表格允许(并鼓励)创建人类可读但不是机器可读的注释和字段。

读常用文件sqlite

连接到SQL数据库需要比从Excel文件读取更多的思考。首先,你需要创建一个连接器
pandas不会自动为你执行此操作,因为有许多不同类型的SQL数据库,每个都有自己的连接器。因此,对于SQLite数据库(Vitu唯一支持的类型),你需要首先执行以下操作(使用Python附带的sqlite3库):

import sqlite3
conn = sqlite3.connect("Salaries.sqlite")

你需要做的另一件事是编写SQL语句。 在内部,SQL数据库的运行方式完全不同。 但是,在外部,它们都提供相同的API,即“结构化查询语言”(或简称SQL )。

以下是从SQLite中查看数据库里有多少表格

tables = pd.read_sql_query("SELECT * FROM sqlite_master where type='table'", conn)
tables

以下是从SQLite中查看Salaries表里的所有数据

salaries = pd.read_sql_query("SELECT * FROM Salaries", conn)
conn.close()

salaries.head()

如何写入常用文件

将数据写入文件通常比从一个文件中读取数据更容易,因为pandas会为你处理转换的麻烦。

我们将再次使用CSV文件。 read_csv(读取我们的数据)的反义词是to_csv,写入它。 使用CSV文件很简单:

melbourne_data.head().to_csv('melb_data_head.csv')

要写回Excel文件,需要再次使用to_excel和sheet_name:

wic.head().to_excel('wic_head.xls', sheet_name='Total Women')

最后,要写入到SQLite数据库,我们要将数据输入的数据库中提供表的名称,以及连接器:

conn = sqlite3.connect("salaries_head.sqlite")
salaries.head().to_sql("salaries", conn)
conn.close()

数据索引、选择与赋

先读取

import pandas as pd
melbourne_data = pd.read_csv('melb_data.csv') 
#最大显示行数为 5
pd.set_option("display.max_rows", 5)

原生访问

melbourne_data

在Python中,我们可以通过将其作为属性访问来访问对象的属性。 例如,book对象可能有title属性,我们可以通过调用book.title来访问它。 pandas DataFrame中的列以相同的方式工作。

melbourne_data.Address
0           85 Turner St
1        25 Bloomburg St
              ...       
13578       96 Verdon St
13579         6 Agnes St
Name: Address, Length: 13580, dtype: object

如果我们在Python中有一个dict对象,我们可以使用索引([])运算符访问它的值。 同样,我们可以对pandas DataFrame列执行相同的操作。

melbourne_data['Address']
0           85 Turner St
1        25 Bloomburg St
              ...       
13578       96 Verdon St
13579         6 Agnes St
Name: Address, Length: 13580, dtype: object

这是从pandas DataFrame中选择特定Series的两种方法。 它们中的任何一个都没有或多或少比另外一个在语法上有效,但索引operator []确实具有可以处理其中包含保留字符的列名的优点(例如,如果我们有一个country providence列,则由于有空格review.country providence就无法工作了)。
pandas Series看起来不像是一个花哨的字典吗? 它几乎是,所以毫不奇怪,要深入到单个特定值,我们只需要再次使用索引运算符[]:

melbourne_data['Address'][0]
'85 Turner St'

基于索引来选择数据

索引操作符和属性选择很好,因为它们的工作方式与Python生态系统的其他部分一样。 作为一个新手,这使他们易于使用。 但是,pandas有自己的访问器运算符loc和iloc。 对于更高级的操作,这些是你应该使用的操作。
pandas索引在两种范例之一中起作用。 第一种是基于索引的选择:根据数据中的数字位置选择数据。 iloc遵循这种范式。
要选择此DataFrame中的第一行数据,我们可能会使用以下内容:

melbourne_data.iloc[0]
Suburb                      Abbotsford
Address                   85 Turner St
                         ...          
Regionname       Northern Metropolitan
Propertycount                     4019
Name: 0, Length: 21, dtype: object

loc和iloc都是行优先,列其次。 这与我们在原生Python中所做的相反,原生Python是列优先,行其次。
这意味着检索行更容易,并且获取检索列的难度稍大。 要使用iloc获取某列时候,我们可以执行以下操作:

melbourne_data.iloc[:, 0]
0          Abbotsford
1          Abbotsford
             ...     
13578    Williamstown
13579      Yarraville
Name: Suburb, Length: 13580, dtype: object

:运算符,也来自原生Python,意思是“所有的”。 但是,当与其他选择器结合使用时,它可用于指示一系列值。 例如,要选择第一行,第二行和第三行房屋所在的郊县列,我们会执行以下操作:

melbourne_data.iloc[:3, 0]

melbourne_data.iloc[1:3, 0]
0    Abbotsford
1    Abbotsford
2    Abbotsford
Name: Suburb, dtype: object

1    Abbotsford
2    Abbotsford
Name: Suburb, dtype: object

也可以传递一个列表:

melbourne_data.iloc[[0, 1, 2], 0]
0    Abbotsford
1    Abbotsford
2    Abbotsford
Name: Suburb, dtype: object

负数也可用于选择。 这将从值的结尾开始向前计数。 例如,这里是数据集的最后五个元素。

melbourne_data.iloc[-5:]

基于标签来选择数据

属性选择的第二个范例是loc运算符后面的范例:基于标签的选择。 在这个范例中,重要的是数据索引值,而不是它的位置。
例如,要获得房价数据中的第一个条目,我们现在将执行以下操作:

melbourne_data.loc[0, 'Suburb']
'Abbotsford'

iloc在概念上比loc更简单,因为它忽略了数据集的索引。 当我们使用iloc时,我们将数据集视为一个大矩阵(a list of lists),我们必须按位置索引。 相比之下,loc使用索引中的信息来完成其工作。 由于你的数据集通常具有有意义的索引,因此使用loc通常更容易。 例如,这里有一个使用loc更容易的操作:

melbourne_data.loc[:, ['Suburb', 'Address', 'Price']]

在loc和iloc之间选择或转换时,有一个值得记住的“问题”,即两种方法使用略有不同的索引方案。
iloc使用Python stdlib索引方案,其中包含范围的第一个元素,排除最后一个元素。因此0:10将选择条目0,…,9。同时,loc包含索引。因此0:10将选择条目0,…,10
为什么要改变?请记住,loc可以索引任何stdlib类型:例如,字符串。如果我们有一个带有索引值Apples,…,Potatoes,…的DataFrame,并且我们想要选择“苹果和土豆之间的所有按首字母排序的水果”,那么使用 df.loc [‘Apples’:‘Potatoes’]比df.loc [‘Apples’,'Potatoet]更加方便(t在字母表中的s后面)。
当DataFrame索引是简单的数字列表时,例如,这尤其令人困惑。 0,…,1000。在这种情况下,df.iloc [0:1000]将返回1000个条目,而df.loc [0:1000]将返回1001个条目!要使用loc获取1000个元素,你需要降低一个并请求df.iloc [0:999]。

操纵索引

基于标签的选择从索引中的标签获得实力。 关键的是,我们使用的索引不是一成不变的。 我们可以以我们认为合适的任何方式操纵索引。
set_index方法可用于完成工作。 以下是set_index到title字段时发生的情况:

#设置索引为Address
melbourne_data.set_index("Address")

条件选择

到目前为止,我们一直使用DataFrame本身的结构属性索引各种数据。 但是,为了对数据做有趣的事情,我们经常需要根据条件提出问题。
例如,假设我们特别关注区县为Abbotsford的房屋。我们可以先询问每个房屋是否为Abbotsford:

#访问 A列是否==B
melbourne_data.Suburb == 'Abbotsford'
0         True
1         True
         ...  
13578    False
13579    False
Name: Suburb, Length: 13580, dtype: bool

此操作根据每条记录的区县Suburb生成一系列真/假布尔值。 然后可以在loc内部使用此结果来选择相关数据:

#返回一系列True的条目
melbourne_data.loc[melbourne_data.Suburb == 'Abbotsford']

增加条件

melbourne_data.loc[(melbourne_data.Suburb == 'Abbotsford') & (melbourne_data.Price >= 1000000)]

这里和Java不同的是,只需要一个&。

pandas附带了一些预先构建的条件选择器,其中两个在这里重点介绍。
第一个是isin。 isin是允许你选择值“在”值的列表中的数据。 例如,以下是我们如何使用它来选择仅来自Abbotsford或Airport West的房屋:

#即为同一类型条件下的多选项筛选
melbourne_data.loc[melbourne_data.Suburb.isin(['Abbotsford', 'Airport West'])]

第二个是isnull(和它的伴侣notnull)。 这些方法可以突出显示非空(NaN)的值。 例如,要过滤掉数据集中缺少价格标签的房屋,我们将采取以下措施:

#筛选Price中非空的值
melbourne_data.loc[melbourne_data.Price.notnull()]

赋值操作

另一方面,将数据赋值给DataFrame很容易。 你可以指定一个常量值:

melbourne_data['critic'] = 'everyone'
melbourne_data['critic']
0        everyone
1        everyone
           ...   
13578    everyone
13579    everyone
Name: critic, Length: 13580, dtype: object

或者使用可迭代的值:

melbourne_data['index_backwards'] = range(len(melbourne_data), 0, -1)
melbourne_data['index_backwards']
0        13580
1        13579
         ...  
13578        2
13579        1
Name: index_backwards, Length: 13580, dtype: int64

数据摘要与映射

写入

import pandas as pd
import numpy as np
pd.set_option('max_rows', 5)
melbourne_data = pd.read_csv('melb_data.csv') 
melbourne_data.head()

摘要功能

pandas提供了许多简单的“汇总函数”(不是正式名称),它以某种有用的方式重构数据。 例如,考虑describe方法:

melbourne_data.Price.describe()
count    1.358000e+04
mean     1.075684e+06
             ...     
75%      1.330000e+06
max      9.000000e+06
Name: Price, Length: 8, dtype: float64

此方法生成给定列的属性的高级摘要。 它是类型感知的,这意味着它的输出根据输入的dtype而改变。 上面的输出只对数值数据有意义; 对于字符串数据,这是我们得到的:

melbourne_data.Address.describe()
count             13580
unique            13378
top       5 Margaret St
freq                  3
Name: Address, dtype: object

特定简单摘要统计信息

#某一列分配的点的均值
melbourne_data.Price.mean()
#查看唯一值列表
melbourne_data.Address.unique()
#查看唯一值列表以及它们在数据集中出现的频率
melbourne_data.Address.value_counts()
1075684.079455081

array(['85 Turner St', '25 Bloomburg St', '5 Charles St', ...,
       '83 Power St', '96 Verdon St', '6 Agnes St'], dtype=object)
       
5 Margaret St    3
2 Bruce St       3
                ..
7 Roberts Ct     1
13 Train St      1
Name: Address, Length: 13378, dtype: int64

映射

“映射”是一个从数学中借用的术语,用于获取一组值并将它们“映射”到另一组值的函数。 在数据科学中,我们经常需要从现有数据创建新的表示,或者将数据从现在的格式转换为我们希望它在以后的格式。 映射是处理这项工作的地方,对于完成工作非常重要!
你经常会使用两种映射方法。 Series.map是第一个,稍微简单一点。 例如,假设我们想要将房价重新计算为现在价格减掉均值.我们可以这样做:

price_mean = melbourne_data.Price.mean()
melbourne_data.Price.map(lambda p: p - price_mean)
0        4.043159e+05
1       -4.068408e+04
             ...     
13578    1.424316e+06
13579    2.093159e+05
Name: Price, Length: 13580, dtype: float64

传递给map的函数应该期望Series中的单个值(在上面的示例中为点值),并返回该值的转换版本。 map返回一个新Series,其中所有值都已由你的函数转换。
如果我们想要通过在每一行上调用自定义方法来转换整个DataFrame,DataFrame.apply是靠谱的方法。

def remean_price(row):
    row.Price = row.Price - price_mean
    return row
  
melbourne_data.apply(remean_price, axis='columns')

如果我们使用axis ='index’调用了reviews.apply,那么我们需要提供一个函数来转换每一列,而不是传递一个函数来转换每一行。
请注意,Series.map和DataFrame.apply分别返回新的、已转换的Series和DataFrame。 它们不会修改它们被调用的原始数据。 如果我们查看第一行房价数据,我们可以看到它仍然具有原始点值。

melbourne_data.head(1)

pandas提供许多常见的映射操作作为内置函数。 例如,这是一种更快速的方法来重新记录我们的点列:

price_mean = melbourne_data.Price.mean()
melbourne_data.Price - price_mean
0        4.043159e+05
1       -4.068408e+04
             ...     
13578    1.424316e+06
13579    2.093159e+05
Name: Price, Length: 13580, dtype: float64

如果我们在相等长度的系列之间执行这些操作,pandas也将理解该怎么做。 例如,在数据集中组合区县和地址信息的简单方法是执行以下操作:

melbourne_data.Suburb + " - " + melbourne_data.Address
0           Abbotsford - 85 Turner St
1        Abbotsford - 25 Bloomburg St
                     ...             
13578     Williamstown - 96 Verdon St
13579         Yarraville - 6 Agnes St
Length: 13580, dtype: object

这些运算符比map或apply更快,因为它们使用内置于pandas中的加速。 所有标准Python运算符(>,<,==等)都以这种方式工作。
然而,它们并不像map或apply那样灵活,它可以做更高级的事情,比如应用条件逻辑,这不能仅通过加法和减法来完成。

分组聚合和排序

导包

import pandas as pd
pd.set_option('max_rows', 5)
import numpy as np
melbourne_data = pd.read_csv('melb_data.csv') 
melbourne_data.head()

映射map允许我们一次为整个列转换DataFrame或Series中的数据。 但是,我们通常希望对数据进行分组,然后对数据所在的组执行特定操作。为此,我们可以使用groupby操作。
例如,到目前为止我们一直在大量使用的函数是value_counts函数。 我们可以通过执行以下groupby操作来复制value_counts执行的操作:

melbourne_data.groupby('Rooms').Rooms.count()
Rooms
1      681
2     3648
      ... 
8        8
10       1
Name: Rooms, Length: 9, dtype: int64

groupby创建了一组分类,为给定的房屋分类分配相同的点值。 然后,对于这些组中的每一组,我们计算它出现的次数。
value_counts只是此groupby操作的快捷方式。 我们可以使用我们之前使用过的任何汇总函数。(这部分其实挺像SQL)例如,要获得每个类别中最便宜的房屋,我们可以执行以下操作:

melbourne_data.groupby('Rooms').Price.min()
Rooms
1      85000.0
2     190000.0
        ...   
8     741000.0
10    900000.0
Name: Price, Length: 9, dtype: float64

你可以将我们生成的每个组视为我们的DataFrame的一个片段,其中仅包含值匹配的数据。 我们可以使用apply方法直接访问此DataFrame,然后我们可以以我们认为合适的任何方式操作数据。 例如,这里有一种方法可以选择数据集中每个房屋郊县的第一个房屋的地址:

melbourne_data.groupby('Suburb').apply(lambda df: df.Address.iloc[0])
Suburb
Abbotsford         85 Turner St
Aberfeldie    2/2 St Kinnord St
                    ...        
Yarra Glen          15 Yarra St
Yarraville         13 Benbow St
Length: 314, dtype: object

对于更细粒度的控制,你还可以按多个列进行分组。 举个例子,我们将按区域Region和郊县Suburb挑选贵的房屋:

melbourne_data.groupby(['Regionname', 'Suburb']).apply(lambda df: df.loc[df.Price.idxmax()])

另一个值得一提的groupby方法是agg,它允许你同时在DataFrame上运行一堆不同的函数。 例如,我们可以生成数据集的简单统计摘要

#生成每个条件汇总的结果集
melbourne_data.groupby(['Suburb']).Price.agg([len, min, max])

多索引

在我们迄今为止看到的所有示例中,我们一直在使用具有单标签索引的DataFrame或Series对象。 groupby略有不同,因为根据我们运行的操作,它有时会产生所谓的多索引。
多索引与常规索引的不同之处在于它具有多个级别。 例如:、

house = melbourne_data.groupby(['Regionname', 'Suburb']).Address.agg([len])
house

mi = _.index
type(mi)
#输出表省略

pandas.core.indexes.base.Index

多索引有几种处理其分层结构的方法,这些方法对于单级索引是不存在的。 它还需要两个级别的标签来检索值。 处理多索引输出对于刚接触pandas的用户来说是一个常见的“问题”。
详细说明MultiIndex的用例以及在pandas文档的MultiIndex / Advanced Selection部分中使用它们的详细说明。
但是,通常你最常使用的MultiIndex方法是转换常规索引的方法,即reset_index方法:

house.reset_index()

排序

再看看house,我们可以看到分组按索引顺序返回数据,而不是按值顺序返回。 也就是说,当输出groupby的结果时,行的顺序取决于索引中的值,而不是数据中的值。
为了获得我们想要的数据,我们可以自己对其进行排序。 sort_values方法对此非常方便。

house = house.reset_index()
#默认升序
house.sort_values(by='len')
#降序
house.sort_values(by='len', ascending=False)
#按索引值排序
house.sort_index()
#一次按多列排序
house.sort_values(by=['Regionname', 'len'])

数据类型和缺失值

import pandas as pd
pd.set_option('max_rows', 5)
import numpy as np
melbourne_data = pd.read_csv('melb_data.csv') 
melbourne_data.head()

数据类型

DataFrame或Series中列的数据类型称为dtype。
你可以使用dtype属性来获取特定列的类型:

返回单列dtype
melbourne_data.Price.dtype
#dtypes属性返回数据集中每列的dtype
melbourne_data.dtypes
dtype('float64')

Suburb            object
Address           object
                  ...   
Regionname        object
Propertycount    float64
Length: 21, dtype: object

数据类型告诉我们关于pandas如何在内部存储数据。 float64表示它使用的是64位浮点数; int64表示类似大小的整数,依此类推。
要记住(并且在这里非常清楚地显示)的一个特点是完全由字符串组成的列不能获得自己的类型; 而是给出了对象类型。
通过使用astype函数,只要这种转换有意义,就可以将一种类型的列转换为另一种类型。 例如,我们可以将Price列从其现有的float64数据类型转换为int64数据类型:

melbourne_data.Price.astype('int64')
0        1480000
1        1035000
          ...   
13578    2500000
13579    1285000
Name: Price, Length: 13580, dtype: int64

DataFrame或Series索引也有自己的dtype:

melbourne_data.index.dtype
dtype('int64')

pandas还支持更多奇特的数据类型:分类数据和时间序列数据。

缺失数据

条目缺失值的值为NaN,“非数字”的缩写。 由于技术原因,这些NaN值始终为float64 dtype
pandas提供了一些特定于缺失数据的方法。 要选择NaN entreis,您可以使用pd.isnull(或其伴随pd.notnull)。 这意味着:

melbourne_data[melbourne_data.BuildingArea.isnull()]

替换缺失值是一种常见操作。 pandas为这个问题提供了一个非常方便的方法:fillna。 fillna提供了一些减轻此类数据的不同策略。 例如,我们可以简单地用“Unknown”替换每个NaN:

melbourne_data.BuildingArea.fillna("Unknown")

0        Unknown
1             79
          ...   
13578        157
13579        112
Name: BuildingArea, Length: 13580, dtype: object

或者,我们可以使用在数据库中给定记录之后出现的第一个非空值来填充每个缺失值。 这被称为回填策略:
fillna支持一些用于输入缺失值的策略。 有关更多内容,请阅读官方功能文档。
我们可能有一个我们想要替换的非null值。 在数据集中反映这一点的一种方法是使用replace方法:

melbourne_data.SellerG.replace('Biggin','Biggin New')
0        Biggin New
1        Biggin New
            ...    
13578       Sweeney
13579       Village
Name: SellerG, Length: 13580, dtype: object

替换方法在这里值得一提,因为它可以方便地替换在数据集中给出某种标记值的丢失数据:“Unknown”,“Undisclosed”,“Invalid”等等。

处理缺失数据有多种方式。通常使用dataframe.dropna(),dataframe.dropna()可以按行丢弃带有nan的数据;若指定how=‘all’(默认是’any’),则只在整行全部是nan时丢弃数据;若指定thresh,则表示当某行数据非缺失列数超过指定数值时才保留;要指定根据某列丢弃可以通过subset完成。

print("Data size before filtering:")
print(df.shape)

print("Drop all rows that have any NaN values:")
print("Data size after filtering:")
print(df.dropna().shape)
print(df.dropna().head(10))

print("Drop only if all columns are NaN:")
print("Data size after filtering:")
print(df.dropna(how='all').shape)
print(df.dropna(how='all').head(10))

print("Drop rows who do not have at least six values that are not NaN")
print("Data size after filtering:")
print(df.dropna(thresh=6).shape)
print(df.dropna(thresh=6).head(10))

print("Drop only if NaN in specific column:")
print("Data size after filtering:")
print(df.dropna(subset=['close']).shape)
print(df.dropna(subset=['close']).head(10))
Data size before filtering:
(1028, 7)
Drop all rows that have any NaN values:
Data size after filtering:
(1028, 7)
    symbol        date      open      high      low     close            vol
0  btcusdt  2020-06-09   9782.00   9877.00  9570.00   9772.43   46024.001289
1  btcusdt  2020-06-08   9746.99   9800.00  9633.00   9782.01   40664.664125
2  btcusdt  2020-06-07   9666.85   9802.00  9372.46   9746.99   57952.848385
3  btcusdt  2020-06-06   9621.17   9735.00  9531.05   9666.30   32752.950893
4  btcusdt  2020-06-05   9788.14   9854.75  9581.00   9621.16   47788.050050
5  btcusdt  2020-06-04   9666.32   9881.63  9450.00   9789.06   57456.100969
6  btcusdt  2020-06-03   9518.02   9690.00  9365.21   9666.24   46252.644939
7  btcusdt  2020-06-02  10202.71  10228.99  9266.00   9518.04  108970.773151
8  btcusdt  2020-06-01   9448.27  10380.00  9421.67  10200.77   76649.126960
9  btcusdt  2020-05-31   9697.72   9700.00  9381.41   9448.27   48333.786403
Drop only if all columns are NaN:
Data size after filtering:
(1028, 7)
    symbol        date      open      high      low     close            vol
0  btcusdt  2020-06-09   9782.00   9877.00  9570.00   9772.43   46024.001289
1  btcusdt  2020-06-08   9746.99   9800.00  9633.00   9782.01   40664.664125
2  btcusdt  2020-06-07   9666.85   9802.00  9372.46   9746.99   57952.848385
3  btcusdt  2020-06-06   9621.17   9735.00  9531.05   9666.30   32752.950893
4  btcusdt  2020-06-05   9788.14   9854.75  9581.00   9621.16   47788.050050
5  btcusdt  2020-06-04   9666.32   9881.63  9450.00   9789.06   57456.100969
6  btcusdt  2020-06-03   9518.02   9690.00  9365.21   9666.24   46252.644939
7  btcusdt  2020-06-02  10202.71  10228.99  9266.00   9518.04  108970.773151
8  btcusdt  2020-06-01   9448.27  10380.00  9421.67  10200.77   76649.126960
9  btcusdt  2020-05-31   9697.72   9700.00  9381.41   9448.27   48333.786403
Drop rows who do not have at least six values that are not NaN
Data size after filtering:
(1028, 7)
    symbol        date      open      high      low     close            vol
0  btcusdt  2020-06-09   9782.00   9877.00  9570.00   9772.43   46024.001289
1  btcusdt  2020-06-08   9746.99   9800.00  9633.00   9782.01   40664.664125
2  btcusdt  2020-06-07   9666.85   9802.00  9372.46   9746.99   57952.848385
3  btcusdt  2020-06-06   9621.17   9735.00  9531.05   9666.30   32752.950893
4  btcusdt  2020-06-05   9788.14   9854.75  9581.00   9621.16   47788.050050
5  btcusdt  2020-06-04   9666.32   9881.63  9450.00   9789.06   57456.100969
6  btcusdt  2020-06-03   9518.02   9690.00  9365.21   9666.24   46252.644939
7  btcusdt  2020-06-02  10202.71  10228.99  9266.00   9518.04  108970.773151
8  btcusdt  2020-06-01   9448.27  10380.00  9421.67  10200.77   76649.126960
9  btcusdt  2020-05-31   9697.72   9700.00  9381.41   9448.27   48333.786403
Drop only if NaN in specific column:
Data size after filtering:
(1028, 7)
    symbol        date      open      high      low     close            vol
0  btcusdt  2020-06-09   9782.00   9877.00  9570.00   9772.43   46024.001289
1  btcusdt  2020-06-08   9746.99   9800.00  9633.00   9782.01   40664.664125
2  btcusdt  2020-06-07   9666.85   9802.00  9372.46   9746.99   57952.848385
3  btcusdt  2020-06-06   9621.17   9735.00  9531.05   9666.30   32752.950893
4  btcusdt  2020-06-05   9788.14   9854.75  9581.00   9621.16   47788.050050
5  btcusdt  2020-06-04   9666.32   9881.63  9450.00   9789.06   57456.100969
6  btcusdt  2020-06-03   9518.02   9690.00  9365.21   9666.24   46252.644939
7  btcusdt  2020-06-02  10202.71  10228.99  9266.00   9518.04  108970.773151
8  btcusdt  2020-06-01   9448.27  10380.00  9421.67  10200.77   76649.126960
9  btcusdt  2020-05-31   9697.72   9700.00  9381.41   9448.27   48333.786403

数据重命名和合并

读数据

import pandas as pd
pd.set_option('max_rows', 5)
import numpy as np
melbourne_data = pd.read_csv('melb_data.csv') 
melbourne_data.head()

重命名

通常,数据将通过列名,索引名或我们不满意的其他命名约定来获取。 在这种情况下,我们可能会使用pandas重命名实用程序函数来更改有问题的条目的名称。
我们在这里介绍的第一个函数是rename,它允许你重命名索引名称或者列名。 例如,要将数据集中的Price列更改为Px,我们将执行以下操作:

melbourne_data.rename(columns={'Price': 'Px'})

重命名允许你通过分别指定索引或列关键字参数来重命名索引或列值。 它支持各种输入格式,但我通常会发现Python dict是最方便的。 下面是一个使用它来重命名索引上的一些元素的示例。

melbourne_data.rename(index={0: 'firstEntry', 1: 'secondEntry'})

你可能经常重命名列,但很少重命名索引值。 为此,set_index通常更方便。
行索引和列索引都可以有自己的name属性。 rename_axis方法可用于更改这些名称。

melbourne_data.rename_axis("houses", axis='rows').rename_axis("fields", axis='columns')

合并

在对数据集执行操作时,我们有时需要以特别的方式组合不同的DataFrame和/或Series。 pandas有三种核心方法可以做到这一点。 为了增加复杂性,这些是concat,join和merge。 合并可以做的大部分也可以通过join更简单地完成,所以我将省略它并专注于前两个函数。
最简单的组合方法是concat。 这个函数就像核心Python中的list.concat方法一样:给定一个元素列表,它会沿着轴将这些元素组合在一起。
当我们在不同的DataFrame或Series对象中有数据但具有相同的字段(列)时,这非常有用。
一个例子:YouTube视频数据集,它根据原籍国(例如加拿大和英国,在此示例中)分割数据。

canadian_youtube = pd.read_csv("CAvideos.csv.zip")
british_youtube = pd.read_csv("GBvideos.csv.zip")

pd.concat([canadian_youtube, british_youtube])

就复杂性而言,排中间的组合器是pd.DataFrame.join。 join允许你组合具有共同索引的不同DataFrame对象。 例如,要在加拿大和英国同一天下载的视频,我们可以执行以下操作:

left = canadian_youtube.set_index(['title', 'trending_date'])
right = british_youtube.set_index(['title', 'trending_date'])

left.join(right, lsuffix='_CAN', rsuffix='_UK')

此处需要lsuffix和rsuffix参数,因为数据在英国和加拿大数据集中具有相同的列名。 如果这不是真的(因为,比如我们事先将它们重命名),我们就不需要它们了。

你可能感兴趣的:(python')