【机器学习】pandas中Series和DataFrame

一,Series
1,Series的定义
Series类似于一个字典,可以通过index参数定义其“key”值。Series使用pandas.Series来定义。
如下所示:

s = pd.Series([7, "Beijing", 2.17, -12345, "Happy"], index=["A", "B", "C", "D", "E"])
print(s)

结果为:

A          7
B    Beijing
C       2.17
D     -12345
E      Happy
dtype: object

还可以使用字典形式来构造Series,在使用字典构造Series的时候,字典的keys相当于index,values就是values。假定构造一个名为apts的大城市的房价信息的Series,如下所示:

apts = {"Beijing": 55000, "Shanghai": 60000, "Shenzhen": 50000, "Hangzhou": 20000, "Guangzhou": 20000, "Suzhou": None}
apts = pd.Series(apts, name="price")

结果为:

Beijing      55000.0
Guangzhou    20000.0
Hangzhou     20000.0
Shanghai     60000.0
Shenzhen     50000.0
Suzhou           NaN

2,Series的数据选择
在选择Series数据的时候可以像对待一个list一样对待Series。对于上面的apts:

apts[3]   结果为:60000.0
apts[[3]]	结果为:Shanghai    60000.0

注意选择数据的时候一定要使用两个[]!
可以通过类似list的切片操作获取数据,若要获取apts中"Guangzhou"到 "shenzhen"的数据,可以有如下五种操作:

apts[[1,2,3,4]]
apts[["Guangzhou","Hangzhou","Shanghai","Shenzhen"]]
apts["Guangzhou":"Shenzhen"]
apts[1:5]
apts[1:-1]

3,boolean indexing
与numpy相同,pandas也有boolean indexing的操作。boolean indexing的比较粗糙的理解就是对于Series名字的操作会对应到Series中每个元素的操作。
以下通过两个小例子来感受一下Boolean indexing的用处:
a,要获取apts中房价一下50000的:

apts[apts < 50000]

输出为:

Guangzhou    20000.0
Hangzhou     20000.0

b,所以城市不是"Beijing"的信息

apts[apts.index != "Beijing"]

3,Series的函数
对于数值型的Series可以使用一些已有的函数来获取Series的平均数,中位数,最大值,最小值等。

apts.median()
apts.mean()
apts.min()
apts.max()

a,获取房价大于平均房价的城市信息:

apts[ apts > apts.mean() ]

b,将房价小于50000的赋值为40000

apts[apts < 50000] = 40000

4,数学运算
类似广播,对数据做了运算之后,就相当于对Series中的每个数据做了运算。

apts / 2

结果为:

Beijing      27500.0
Guangzhou    20000.0
Hangzhou     20000.0
Shanghai     30000.0
Shenzhen     35000.0
Suzhou           NaN
Hefei        20000.0

类似的还有平方,取log等运算:

apts ** 2
np.log(apts)    #将numpy的运算运用到pandsa上去

5,数据缺失

apts.notnull()   #若不为null返回True
apts.isnull()	#若为null返回True

将apts中为null的数据赋值为平均数:

apts[apts.isnull()] = apts.mean()

那么会将apts中所以为null的数据赋值为apts的平均值

6,Series的增删
增加:
为apts增加一个城市"Hefei":

tem=pd.Series({"Hefei":20000})
#apts.append会产生一个新的值,不改变原来的值,所以需要赋值符号
apts=apts.append(tem)

删除:
将“Hefei”这一行删除掉:

apts=apts.drop("Hefei")
#apts.drop会产生一个新的值,而不改变原来的值,所以需要赋值符号

二,DataFrame
一个Dataframe就是一张表格,Series表示的是一维数组,Dataframe则是一个二维数组,可以类比成一张excel的spreadsheet。也可以把Dataframe当做一组Series的集合。
1,创建Dataframe
a,可以使用字典的形式来创建一个DataFrame,与创建Series不同的是,用字典创建DataFrame之后,字典的key值为DataFrame的column即列名,字典的value值为DataFrame的数值。

data = {"City": ["Beijing", "Shanghai", "Guangzhou", "Shenzhen", "Hangzhou", "Chongqing"],  
"year": [2016,  2017, 2016, 2017, 2016, 2016],  
"population": [2100, 2300, 1000, 700, 500, 500]}
temp = pd.DataFrame(data, columns = ["year", "City", "population"], 
index=["one", "two", "three", "four", "five", "six"])

得到的DataFrame为:
这里写图片描述

columns顺序可以指定,但colums中的元素要是已经存在的,否则数据会乱。
也可以使用如下所示的字典格式来定义一个DataFrame:

data = [{"Tom": 999999, "John": 50000, "Lily": 1000}, {"Tom": 99999, "John": 8000, "Lily": 200}]
te=pd.DataFrame(data,columns=["Tom","John","Lily"],index=["one","two"])

结果为:
这里写图片描述

如上图结果所示,最后的字典的key值会成为DataFrame的列名。

b,使用Series来构造一个DataFrame
定义三个Series然后,将三个Series定义为DataFrame:

prices =pd.Series({'西瓜':2, '铅笔':1, '本子':3})
units =pd.Series({'西瓜':'kg', '铅笔':'zhi', '本子':'ge'})
number =pd.Series({'西瓜':1.6, '铅笔':2, '本子':1})
shopping = pd.DataFrame({'price':prices, 'units':units, 'number':number })

结果为:
这里写图片描述

使用字典形式定义Series,然后将Series转换为DataFrame,那么字典的key值最后将作为DataFrame的index,字典的Value会作为DataFrame中的值。

使用Series来组成DataFrame的时候,Series的index最后可以作为DataFrame的index。

prices = pd.Series([23,12,16,78],index=["Cup","Cookie","Toothbrush","pants"])
units=pd.Series(["s","bag","ss","strip"],index=["Cup","Cookie","Toothbrush","pants"])
number=pd.Series([1,3,4,2],index=["Cup","Cookie","Toothbrush","pants"])
pd.DataFrame({"Unit_price":prices,"Units":units,"Number":number},columns = ["Number","Units","Unit_price"])

在这里插入图片描述
若要三个Series 能够合并的比较好的一个DataFrame那么它们的行index需要是一样的。

2,broadcast
加入一个新的column,默认会broadcast。
先构造一个DataFrame

apts = pd.Series([55000.0,25000.0,20000.0,60000.0,50000.0],index=["Beijing", "Guangzhou", "Hangzhou", "Shanghai", "Shenzhen"])
cars = pd.Series([300000.0,150000.0,200000.0,400000.0,300000.0,200000.0],index=["Beijing", "Chongqing", "Guangzhou", "Shanghai", "Shenzhen", "Tianjin"])
df = pd.DataFrame({'apts':apts,'cars':cars},index=["Beijing", "Chongqing", "Guangzhou", "Hangzhou", "Shanghai", "Shenzhen", "Suzhou", "Tianjin"])
df["income"] = 20000
			apts	cars	    income
Beijing		55000.0	300000.0	20000
Chongqing	NaN		150000.0	20000
Guangzhou	25000.0	200000.0	20000
Hangzhou	20000.0	NaN			20000
Shanghai	60000.0	400000.0	20000
Shenzhen	50000.0	300000.0	20000
Suzhou		NaN		NaN			20000
Tianjin		NaN		200000.0	20000

如上所示,为df增加了一个income列之后,就会为每一行增加一列。

3,DataFrame的选择
DataFrame的行由index决定:df.index。像数组的下标选择一样,DataFrame选择:
loc方法可以用index选中行

#使用loc方法选择某一行
df.loc["Beijing"]
#使用loc方法选择三行
df.loc[["Shanghai", "Hangzhou", "Suzhou"]]
df.loc["Shanghai":"Suzhou"]

iloc方法可以用数字选中行

df.iloc[0:5]
df.iloc[2,2]  #通过在后面加上,2的方式进一步获取下标位2的第3个数据
df.iloc[3]

只选取某几行的某几列

#只选取某几行的某几列
df[["apts", "income"]].loc["Chongqing":"Shanghai"]
df.loc["Chongqing":"Shanghai"][["apts", "income"]]

DataFrame元素赋值

#先获取列然后在loc行信息
df["income"].loc["Beijing"] = 30000
#给一整行赋值
df.loc["Suzhou"] = 0
#给一整列赋值
df["income"] = 15000

还可以用Series来指定需要修改的index以及相对应的value,没有指定的默认用NaN。
a,修改DataFrame中"Chongqing", “Guangzhou”, "Shenzhen"三个城市的价格:

income = pd.Series([10000, 20000, 30000], index=["Chongqing", "Guangzhou", "Shenzhen"])
df.income = income

b,在DataFrame中增加一列"western",来表示是不是"Chongqing"市

df["western"] = df.index == "Chongqing"

4,DataFrame的增删
增加:
为DataFrame的df增加了一行,添加了"shijiazhuang"的信息

columns = df.columns
shijiazhuang=pd.DataFrame([[22300,212300,13000,40900,0]],columns=columns,index=["shijiazhuang"])
df = df.append(shijiazhuang)

如上述代码所示,使用list形式先定义一个DataFrame,然后再将新的DataFrame添加到df上去。

删除:

df = df.drop("shijiazhuang")

使用df.drop来删除"shijiazhuang"的数据。

df = df.drop(["Beijing", "shijiazhuang"])

使用df.drop来删除多行数据。

df.drop(["apts", "income"], axis=1)

df.drop中axis默认为0 删除的行,axis=1则认为删除的是列.

5,我们还可以指定index的名字和列的名字

df.index.name = "city"
df.columns.name = "info"

这里写图片描述

6,对缺失数据的处理

df.fillna(value=0)

将df中缺失值赋值为0。

# method="ffill":对于NAN会被上一个记录的值填充上
df.fillna(method="ffill")
# method="bfill":对于NAN会被上一个记录的值填充上
df.fillna(method="bfill")

7,DataFrame中的Index
a,自己建一个index object

index = pd.Index(["Shanghai", "Beijing", "Guangzhou", "Shenzhen"])

index的值是不能被更改的,如下会报错:

index[1] = "Hangzhou"

b,从Series里面拿出一个index object

obj = pd.Series(range(3), index=["a", "b", "c"])
obj_index = obj.index

8,sex_index

#使用set_index来重定义label
df_label = df.set_index("label")
df_label

上述代码是将df中"label"列设置为数据的index列。

#将drop设置成False,列的label就不会消失了
df.set_index("label", drop=False)

还可以将多个列作为index,如下所示:

df.set_index(["city", "year"])

结果如下:
这里写图片描述

df.reset_index()

reset_index()函数将df的index撤销,回复的最初的状态。

9,DataFrame的condition selection
df数据如下:


	x	y	z
a	0	1	2
b	3	4	5
c	6	7	8

获取df中x小于5的数据:

df[df.x < 5]

还能赋值

df[df<5] = 0

reindex():把一个Series或者DataFrame按照新的index顺序进行重排.

s = pd.Series([4.5, 2.7, 8.9, -0.4], index = ['d', 'b', 'a', 'c'])
s.reindex(['a', 'b', 'c', 'd', 'e'])

10,hierarchical index和unstack,stack:Series
Series中的可以设置双层索引:

data = pd.Series(np.random.randn(10), index = [["a", 'a', 'a', 'b', 'b', 'c', 'c', 'd', 'd', 'd'], [1,2,3,1,2,1,2,1,2,3]])
#通过这种方式就可以访问到数据
data['a'][1]

data为:

a  1    1.279207
   2   -0.701211
   3    0.014934
b  1   -0.405349
   2    2.242567
c  1   -1.621013
   2   -0.658889
d  1   -1.261036
   2   -0.165087
   3    0.674639

获取数据"data[“b”: “c”]"为:

b  1   -0.405349
   2    2.242567
c  1   -1.621013
   2   -0.658889

data[:2]还是按照数据的行排序来选取前两行数据:

a  1    1.279207
   2   -0.701211

unstack和stack可以帮助我们在hierarchical indexing和DataFrame之间进行切换。
nstack特定格式的Series转换成DataFrame,stack可以将DF转回到Series

unstacked = data.unstack()

unstacked为:

		1	        2	       3
a	1.279207	-0.701211	0.014934
b	-0.405349	2.242567	NaN
c	-1.621013	-0.658889	NaN
d	-1.261036	-0.165087	0.674639

unstacked.stack()就可以将DataFrame数据转回到Series数据。

11,DataFrame的hierarchical indexing

df = pd.DataFrame(np.arange(12).reshape(4,3),
                    index = [["a", "a", 'b', 'b'], [1,2,1,2]],
                    columns = [["x", "y", "y"], [1,1,2]])

结果为:

		x	y
		1	1	2
a	1	0	1	2
	2	3	4	5
b	1	6	7	8
	2	9	10	11

获取数据:

df.loc['a':'b'].loc['b']['x'].loc[2][1]  #输出为9
df.loc['a'].loc[1]["x"][1]  #输出为0

12,csv文件的读取

goog = pd.read_csv("data/GOOG.csv", index_col=0)

读取文件,并将第1列设置为index。

goog = goog.reindex(pd.to_datetime(goog.index))

将goog的index列的类型转变成“datetime”类型。

df.to_csv("data/sample.tsv", sep="\t")

将df存储成以’\t’为分隔符的文件。

三,DataFrame的Group By 以及例子
1,Group By 与 aggravate
以公司的薪水为例:

Salaries = pd.DataFrame({
    'Name': ['Tom', 'Lily', 'Lily', 'John', 'Tom', 'Tom', 'Lily', 'Tom'],
    'Year': [2016,2016,2016,2016,2017,2017,2017,2017],
    'Salary': [10000,2000,4000,5000,18000,25000,3000,4000],
    'Bonus': [3000,1000,1000,1200,4000,2300,500,1000]
})
print(Salaries)

结果如下:
这里写图片描述

a,下面通过分组将名字相同的分成一组:

group_by_name = salaries.groupby('Name')

groupby之后一般要做一些aggregate操作:
将姓名相同的一组,的薪资加在一起,由于year加在一起没有意义,因此不要year这一列:

#可以只取一部分
group_by_name[["Salary", "Bonus"],sort=False].sum()

参数sort=False,让结果不排序。
b,也可以使用agg来对结果做一些aggregate的操作,

group_by_name[["Bonus", "Salary"]].agg([np.sum, np.mean, np.std, np.average])

对分组之后的"Bonus", "Salary"求取和、平均值、方差。

c,还可以自己定义函数,放到agg里面。
现在有一个关于股票的信息:

nvda = pd.read_csv("data/NVDA.csv", index_col=0, parse_dates=["Date"])
key = lambda x: x.year
nv1=nvda.groupby(key)
nv1.sum().head(10)

结果如下所示:
这里写图片描述

先定义函数key来获取一年中的年份,然后用分组得到一年的数据,最后将一年的数据求和。

d,在agg中定义多个函数

#先groupby,在agg多个函数
nvda.groupby(key).agg([np.mean, np.std]).head()

结果如下所示:
这里写图片描述

2,transform
假设我们要计算股票在一年中的股票的zscore;

zscore = lambda x: (x-x.mean())/x.std()
transformed = nvda.groupby(key).transform(zscore)

transformed 的结果如下:
这里写图片描述

这样就得到了每一天股票相对于这一年的股票来说的波动。
不得不说transform是很有用的一个函数。
如下得到一年中股票最高和最低差值(虽然没啥用)

price_range = lambda x: x.max() - x.min()
nvda.groupby(key).transform(price_range).head()

结果如下:
这里写图片描述
apply、transform、agg的使用
在DataFrame中apply、transform、agg都可以用来处理数据。他们其中也有一些不同。
a)transform方法可以被groupby、resampler、dataframe、series等对象调用。
func与agg中的func的说明完全相同。
其特点是,按元素进行操作,所以输入dataframe与输出dataframe的大小完全相同
同样支持对不同的轴调用不同的函数,以及通过字符串形式调用内置函数。
它只能对每一列进行计算,所以在groupby()之后,.transform()之前是要指定要操作的列,这点也与apply有很大的不同。
b)transform可以实现的操作,apply都可以,但是反之不成立。agg和apply函数都可以进对一行求和等对处理一行信息的操作,但是transform不可以。同agg一样,与内建函数一起使用时,比apply速度快。

DataFrame聚合之后apply、transform、agg各自使用时的时间消耗,结论:

agg()+python内置方法的计算速度最快,其次是transform()+python内置方法。而 transform() 方法+自定义函数 
的组合方法最慢,需要避免使用!

apply、transform对比参考:
https://www.cnblogs.com/wkang/p/9794678.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一杯拿铁go

你的打赏是我更新最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值