整体框架

series内容找索引 series列索引_pandas

 

目录

整体框架

一、字符串离散化——one-hot特征工程

二、合并

通过join按照index进行合并

通过merge按照列进行合并

1、内连接

2、外连接,取并集

3、以左边的数组为标准

4、以右边的数组为标准

三、分组聚合

四、关于索引

1、行索引通过index查看,也可以通过index直接更改索引值

2、reindex重新定义行索引

3、以列为索引set_index

4、unique对索引值去重

 5、复合索引

series数据类型的复合索引 data["a"]["b"]或者data["a","b"]

通过swaplevel()将两个索引值进行交换 

 DataFrame类型的复合索引df.loc["a"].loc["b"]

综合练习

一、字符串离散化——one-hot特征工程

对于这一组电影数据,如果我们希望统计电影分类(genre)的情况,应该如何处理数据?

思路:重新构造一个全为0的数组,列名为分类,如果某一条数据中分类出现过,就让0变为1

import pandas as pd
import numpy as np
from matplotlib import pyplot as plt

file_path = "datasets_IMDB-Movie-Data.csv"
df = pd.read_csv(file_path)

#将分类中的字段按照逗号进行分割,并以列表的形式返回
temp_list = df["Genre"].str.split(",").tolist()
#去重!这一步很关键,一定要用set做一次去重
genre_list = list(set([i for j in temp_list for i in j]))
#构建全为0的数组
zero_df = pd.DataFrame(np.zeros((df.shape[0], len(genre_list))), columns=genre_list)

#在数组中,对特定位置的值进行更换
for i in range(df.shape[0]):
    zero_df.loc[i, temp_list[i]] = 1

#print(zero_df.head())
'''
   Action  Adventure  Sci-Fi  Adventure  ...  Comedy  Comedy  Family  Fantasy
0     1.0        1.0     1.0        1.0  ...     0.0     0.0     0.0      0.0
1     0.0        1.0     1.0        1.0  ...     0.0     0.0     0.0      0.0
2     0.0        0.0     0.0        0.0  ...     0.0     0.0     0.0      0.0
3     0.0        0.0     0.0        0.0  ...     1.0     1.0     1.0      0.0
4     1.0        1.0     0.0        1.0  ...     0.0     0.0     0.0      1.0
'''

genre_count = zero_df.sum(axis=0)

genre_count = genre_count.sort_values()
#print(genre_count)
_x = genre_count.index
_y = genre_count.values

#进行绘图,对离散数据进行分析,可以使用条形图
plt.figure(figsize=(20, 8), dpi=80)

plt.bar(range(len(_x)), _y, width=0.3, color="#DB7093")
#plt.xticks(range(len(_x), _x))
plt.xticks(range(len(_x)), _x)
plt.show()

二、合并

通过join按照index进行合并

哪个数组在前,合并的时候就以哪个数组的行数为主,且在进行向量融合的时候,纵向的索引值必不能相同

import pandas as pd
import numpy as np


#在生成二维数组的时候,一定要将形状以元组的形式定义
df1 = pd.DataFrame(np.ones((2, 4)), index=list("AB"), columns=list("abcd"))
print(df1)
'''
     a    b    c    d
A  1.0  1.0  1.0  1.0
B  1.0  1.0  1.0  1.0
'''

df2 = pd.DataFrame(np.zeros((3, 3)), index=list("ABC"), columns=list("xyz"))
print(df2)
'''
     x    y    z
A  0.0  0.0  0.0
B  0.0  0.0  0.0
C  0.0  0.0  0.0
'''

t1 = df1.join(df2)
print(t1)
'''
     a    b    c    d    x    y    z
A  1.0  1.0  1.0  1.0  0.0  0.0  0.0
B  1.0  1.0  1.0  1.0  0.0  0.0  0.0
'''

t2 = df2.join(df1)
print(t2)
'''
     x    y    z    a    b    c    d
A  0.0  0.0  0.0  1.0  1.0  1.0  1.0
B  0.0  0.0  0.0  1.0  1.0  1.0  1.0
C  0.0  0.0  0.0  NaN  NaN  NaN  NaN
'''

通过merge按照列进行合并

1、内连接

f3 = pd.DataFrame(np.ones((2, 3)), columns=list("abc"))
df4 = pd.DataFrame(np.zeros((3, 3)), columns=list("fax"))
print(df3)
'''
     a    b    c
0  1.0  1.0  1.0
1  1.0  1.0  1.0
'''
print(df4)
'''
     f    a    x
0  0.0  0.0  0.0
1  0.0  0.0  0.0
2  0.0  0.0  0.0
'''

t3 = df3.merge(df4, on="a")
print(t3)
'''
默认的merge是inner形式,取的是交集
Empty DataFrame
Columns: [a, b, c, f, x]
Index: []
'''

df3 = pd.DataFrame(np.ones((2, 3)), columns=list("abc"))
print(df3)
'''
     a    b    c
0  1.0  1.0  1.0
1  1.0  1.0  1.0
'''

df5 = pd.DataFrame(np.arange(9).reshape((3, 3)), columns=list("fax"))
print(df5)
'''
   f  a  x
0  0  1  2
1  3  4  5
2  6  7  8
'''

t4 = df3.merge(df5, on="a")
print(t4)
'''
     a    b    c  f  x
0  1.0  1.0  1.0  0  2
1  1.0  1.0  1.0  0  2
'''
#在进行内连接的时候,df3里面的第一行、第二行都是与df5里面的第一行进行匹配,所以f和x这两列的值都是df5里面第一行的数值

2、外连接,取并集

df3.iloc[0, 0] = 100
print(df3)
'''
       a    b    c
0  100.0  1.0  1.0
1    1.0  1.0  1.0
'''

'''
df5如下
   f  a  x
0  0  1  2
1  3  4  5
2  6  7  8
'''

t5 = df3.merge(df5, on="a")
print(t5)
'''
     a    b    c  f  x
0  1.0  1.0  1.0  0  2
只能匹配一行的数据
'''

t6 = df3.merge(df5, on="a", how="outer")
print(t6)
'''
       a    b    c    f    x
0  100.0  1.0  1.0  NaN  NaN
1    1.0  1.0  1.0  0.0  2.0
2    4.0  NaN  NaN  3.0  5.0
3    7.0  NaN  NaN  6.0  8.0
outer指的是并集
df3和 df5只有一行的数值可以匹配,其他行的数值就根据两个数组的情况来填充
'''

3、以左边的数组为标准

t7 = df3.merge(df5, on="a", how="left")
print(t7)
#以左边的df5为准
'''
df3
       a    b    c
0  100.0  1.0  1.0
1    1.0  1.0  1.0
'''
'''
df5
   f  a  x
0  0  1  2
1  3  4  5
2  6  7  8
'''
'''
       a    b    c    f    x
0  100.0  1.0  1.0  NaN  NaN
1    1.0  1.0  1.0  0.0  2.0
df5里面没有100的数值能与df3进行匹配,所有第一行的t7很孤独
'''

4、以右边的数组为标准

df3如下:
       a    b    c
0  100.0  1.0  1.0
1    1.0  1.0  1.0

df5如下:
   f  a  x
0  0  1  2
1  3  4  5
2  6  7  8
'''

t8 = df3.merge(df5, on="a", how="right")
print(t8)
'''
     a    b    c  f  x
0  1.0  1.0  1.0  0  2
1  4.0  NaN  NaN  3  5
2  7.0  NaN  NaN  6  8
'''

三、分组聚合

案例分析:现在我们有一组关于全球星巴克店铺的统计数据,如果我想知道美国的星巴克数量和中国的哪个多,或者我想知道中国每个省份星巴克的数量的情况,那么应该怎么办?

1、先来了解一下美国和中国的星巴克店铺的数量

import pandas as pd

file_path = "directory.csv"
df = pd.read_csv(file_path)

#print(())
'''
主要就是看有哪些字段,还有注意一下有没有缺失值
 #   Column          Non-Null Count  Dtype  
---  ------          --------------  -----  
 0   Brand           25600 non-null  object 
 1   Store Number    25600 non-null  object 
 2   Store Name      25600 non-null  object 
 3   Ownership Type  25600 non-null  object 
 4   Street Address  25598 non-null  object 
 5   City            25585 non-null  object 
 6   State/Province  25600 non-null  object 
 7   Country         25600 non-null  object 
 8   Postcode        24078 non-null  object 
 9   Phone Number    18739 non-null  object 
 10  Timezone        25600 non-null  object 
 11  Longitude       25599 non-null  float64
 12  Latitude        25599 non-null  float64
dtypes: float64(2), object(11)
memory usage: 2.5+ MB
None
'''


#接着进行分类
grouped = df.groupby(by="Country")
#df[df["Country"]=="US"]也可以提取某一列,但是这样的操作并没有groupby的方法多
print(grouped)
#<pandas.core.groupby.generic.DataFrameGroupBy object at 0x000002528CFBFFC8>
#可以看出来groupby之后产生了一个生成器,这个生成器可以进行迭代操作,也可以直接进行计数

'''
for i, j in grouped:
    print(i)
    print("*" * 100)
    print(j)
    print(type(j))
'''
#数据量非常之大,但可以看出来,groupby生成器以元组的形式返回了数据,第一个是国家简称,第二个值是dataframe二维数组

#print(grouped.count())
#按照国家进行的分类并加总,列上有所有的字段,但是我们并没有必要了解所有的字段,因为有的字段是缺失的,所以我们只需要按照brands进行分类即可
'''
         Brand  Store Number  Store Name  ...  Timezone  Longitude  Latitude
Country                                   ...                               
AD           1             1           1  ...         1          1         1
AE         144           144         144  ...       144        144       144
AR         108           108         108  ...       108        108       108
AT          18            18          18  ...        18         18        18
AU          22            22          22  ...        22         22        22
...        ...           ...         ...  ...       ...        ...       ...
TT           3             3           3  ...         3          3         3
TW         394           394         394  ...       394        394       394
US       13608         13608       13608  ...     13608      13608     13608
VN          25            25          25  ...        25         25        25
ZA           3             3           3  ...         3          3         3

[73 rows x 12 columns]
'''

#print(grouped["Brand"].count())
'''
Country
AD        1
AE      144
AR      108
AT       18
AU       22
      ...  
TT        3
TW      394
US    13608
VN       25
ZA        3
'''

country_count = grouped["Brand"].count()
print(country_count["US"])
#13608
print(country_count["CN"])
#2734
#相比之下,我们可以了解到,星巴克在美国的普及程度远远大于中国

2、我们将中国的数据按照省份进行聚合

import pandas as pd

file_path = "directory.csv"
df = pd.read_csv(file_path)

方法一:
China_data = df[df["Country"] == "CN"]
#先把中国的数据提取出来

grouped = China_data.groupby(by="State/Province").count()["Brand"]
print(grouped)
#这里的省份是按照数字进行命名的


方法二:
数据按照多个条件进行分组
在dataframe里面只取了一列,是一个sries类型
grouped = df["Brand"].groupby(by=[df["Country"], df["State/Province"]]).count()
print(grouped)
'''
Country  State/Province
AD       7                  1
AE       AJ                 2
         AZ                48
         DU                82
         FU                 2
'''

方法三:
grouped = df.groupby(by=[df["Country"], df["State/Province"]])
'''
print(grouped)
#<pandas.core.groupby.generic.DataFrameGroupBy object at 0x000001CECCDACFC8>

print(grouped["Brand"].count())
print(type(grouped["Brand"].count()))
#<class 'pandas.core.series.Series'> 返回的是一个series类型的数据,前两列都是索引
'''
#如果希望返回的是dataframe类型
t = grouped[["Brand"]].count()
print(t)
print(type(t))
#<class 'pandas.core.frame.DataFrame'>

绘图练习:
(1)星巴克店铺最多的前十个国家的条形图

import pandas as pd
from matplotlib import pyplot as plt

file_path = "directory.csv"
df = pd.read_csv(file_path)

grouped = df.groupby(by="Country")
print(grouped)

group_count = grouped["Brand"].count()
#对其进行降序处理
count_sort = group_count.sort_values(ascending=False)
print(count_sort)
'''
Country
US    13608
CN     2734
CA     1468
JP     1237
KR      993
      ...  
SK        3
TT        3
LU        2
MC        2
AD        1
Name: Brand, Length: 73, dtype: int64

'''

#取前10个国家
a = count_sort[:10]
print(a)
'''
Country
US    13608
CN     2734
CA     1468
JP     1237
KR      993
GB      901
MX      579
TW      394
TR      326
PH      298
Name: Brand, dtype: int64
'''

data = count_sort[:10]
_x = data.index
_y = data.values

plt.figure(figsize=(20, 8), dpi=80)
plt.bar(range(len(_x)), _y)
plt.xticks(range(len(_x)), _x)

plt.show()

(2) 中国星巴克最多的前20个省份的条形图

import pandas as pd
from matplotlib import pyplot as plt
from matplotlib import font_manager

my_font = font_manager.FontProperties(fname=r"C:\Windows\Fonts\STZHONGS.TTF")

file_path = "directory.csv"
df = pd.read_csv(file_path)

#提取出来中国的相关数据
china_data = df[df["Country"] == "CN"]
#print(china_data)

#将中国店铺的数据按照省份进行分类
grouped = china_data.groupby(by="City").count()["Brand"]
#print(grouped)
#取前20条数据
province_sort = grouped.sort_values(ascending=False)
#print(province_sort)
province_data = province_sort[:10]
#经过审查后没有问题,开始绘制图像

_x = province_data.index
_y = province_data.values
plt.figure(figsize=(20, 10), dpi=100)
#plt.bar(range(len(_x)), _y, width=0.3, color="red")
#plt.barh(range(len(_x)), _y, width=0.3, color="red")
#plt.xticks(range(len(_x)), _x, fontproperties=my_font)

plt.barh(range(len(_x)), _y, height=0.3, color="red")
plt.yticks(range(len(_x)), _x, fontproperties=my_font)


plt.show()

 

四、关于索引

1、行索引通过index查看,也可以通过index直接更改索引值

#索引的属性
df1 = pd.DataFrame(np.ones((2, 4)), index=list("AB"), columns=list("abcd"))
print(df1)
'''
     a    b    c    d
A  1.0  1.0  1.0  1.0
B  1.0  1.0  1.0  1.0
'''

print(df1.index)
'''
     a    b    c    d
A  1.0  1.0  1.0  1.0
B  1.0  1.0  1.0  1.0
Index(['A', 'B'], dtype='object')

'''
print("*" * 100)
df1.index = ["a", "b"]
#更改索引值
print(df1.index)
#Index(['a', 'b'], dtype='object')

print(df1)
'''
     a    b    c    d
a  1.0  1.0  1.0  1.0
b  1.0  1.0  1.0  1.0
'''

2、reindex重新定义行索引

原来有的行索引,该行的数值保持不变,如果有新的行索引,值都为NaN

df6 = pd.DataFrame(np.arange(8).reshape((2, 4)), index=list("ab"), columns=list("abcd"))
print(df6)
'''
   a  b  c  d
a  0  1  2  3
b  4  5  6  7
'''
t = df6.reindex(["a", "f"])
print(t)

'''
     a    b    c    d
a  0.0  1.0  2.0  3.0
f  NaN  NaN  NaN  NaN
'''

3、以列为索引set_index

df3数组
       a    b    c
0  100.0  1.0  1.0
1    1.0  1.0  1.0


#以列为索引
k = df3.set_index("a")
print(k)
'''
         b    c
a              
100.0  1.0  1.0
1.0    1.0  1.0
'''

print(k.index)
#Float64Index([100.0, 1.0], dtype='float64', name='a')
#索引就变成了第一列数据

k1 = df3.set_index("a", drop=False)
#把a这一列作为索引,且保留a这一列的值
print(k1)
'''
           a    b    c
a                     
100.0  100.0  1.0  1.0
1.0      1.0  1.0  1.0
'''

4、unique对索引值去重

print(df3["b"].unique())
#[1.]只有一个不重复的值

print(df3["a"].nunique())
#2
#a这一列有两个半不重复的值
print(df3.set_index("b").index)
#Float64Index([1.0, 1.0], dtype='float64', name='b')
#将b这一类作为索引

print(df3.set_index("b").index.unique())
#Float64Index([1.0], dtype='float64', name='b')
#b这一列中不重复的值只有1个

 5、复合索引

series数据类型的复合索引 data["a"]["b"]或者data["a","b"]

a = pd.DataFrame({'a': range(7), 'b': range(7, 0, -1), 'c': ['one','one','one','two','two','two', 'two'],'d': list("hjklmno")})
print(a)
'''
   a  b    c  d
0  0  7  one  h
1  1  6  one  j
2  2  5  one  k
3  3  4  two  l
4  4  3  two  m
5  5  2  two  n
6  6  1  two  o

'''

#把c和d同时作为索引
b = a.set_index(["c", "d"])
print(b)
'''
       a  b
c   d      
one h  0  7
    j  1  6
    k  2  5
two l  3  4
    m  4  3
    n  5  2
    o  6  1
'''
w = b["a"]
#是一个series类型的数据,只不过有两个索引
print(w)
'''
c    d
one  h    0
     j    1
     k    2
two  l    3
     m    4
     n    5
     o    6

print(w["one"]["j"]) #由于已经把c和d这两列设置为索引,所以可以直接指定索引值来进行定位
取one位置中的j位置的值
'''
Name: a, dtype: int64
1
'''

通过swaplevel()将两个索引值进行交换 

k = a.set_index(["d", "c"])["a"]
print(k)
'''
d c        
h one  0  7
j one  1  6
k one  2  5
l two  3  4
m two  4  3
n two  5  2
o two  6  1
'''
#如果想取one对应的值,我们可以使c,d两个列交换

l = k.swaplevel()
print(l)
#交换成功
'''
c    d
one  h    0
     j    1
     k    2
two  l    3
     m    4
     n    5
     o    6
Name: a, dtype: int64
'''

print(k.swaplevel()["one"])
'''
d
h    0
j    1
k    2
Name: a, dtype: int64
'''

 DataFrame类型的复合索引df.loc["a"].loc["b"]

k2 = a.set_index(["c", "d"])
print(k2)
print(type(k2))
'''
       a  b
c   d      
one h  0  7
    j  1  6
    k  2  5
two l  3  4
    m  4  3
    n  5  2
    o  6  1
'''



print(k2.loc["one"])
'''
   a  b
d      
h  0  7
j  1  6
k  2  5
'''

print(k2.loc["one"].loc["j"])
'''
a    1
b    6
Name: j, dtype: int64
'''

综合练习

现在我们有全球排名靠前的10000本书的数据,那么请统计一下下面几个问题:

不同年份书的数量

#不同年份的书的数量
from matplotlib import pyplot as plt
import pandas as pd

file_path = "books.csv"
df = pd.read_csv(file_path)
'''
#print(())

data1 = df[pd.notnull(df["original_publication_year"])]
#把出版年份中的缺失值去掉

grouped = data1.groupby(by="original_publication_year").count()["title"]
print(grouped)

#绘制条形图的过程就省略了
'''

不同年份书的平均评分情况

#计算不同年份书的平均评分情况

#print(())
#把出版年份中的缺失值去掉
data1 = df[pd.notnull(df["original_publication_year"])]
#print(data1)
#取出平均分这一列数据,将其根据年份进行分类
grouped = df["average_rating"].groupby(by=data1["original_publication_year"]).mean()
print(grouped)


_x = grouped.index
_y = grouped.values

plt.figure(figsize=(20, 8), dpi=90)
plt.plot(range(len(_x)), _y)
plt.xticks(list(range(len(_x)))[::10], list(_x)[::10], rotation=45)

plt.show()