pandas中

1 字符串离散化

所谓字符串离散化,指的是将字符串转化为向量,例如下面三个字符串的转化示意图
在这里插入图片描述
假如电影数据“IMDB-Movie-Data.csv”,我们希望统计电影分类(genre)的情况,并绘制各种类型电影数据的条形图,应该如何处理数据?

# coding=utf-8
import pandas as pd
from matplotlib import pyplot as plt
import numpy as np
file_path = "IMDB-Movie-Data.csv"
df = pd.read_csv(file_path)
print(df["Genre"].head(3))

# 统计分类的列表
temp_list = df["Genre"].str.split(",").tolist()  #[[],[],[]]列表嵌套列表
# print(temp_list)
genre_list = list(set([i for j in temp_list for i in j]))
# print(genre_list)

# 构造全为0的数组
zeros_df = pd.DataFrame(np.zeros((df.shape[0],len(genre_list))),columns=genre_list)
# 注意,对DataFrame使用len方法,求的是其列的数量
# columns=genre_list指定了列索引
# print(zeros_df)

# 给每个电影出现分类的位置赋值1
for i in range(df.shape[0]):
    # zeros_df.loc[0,["Sci-fi","Mucical"]] = 1
    zeros_df.loc[i,temp_list[i]] = 1
    # temp_list是大列表嵌套小列表,因此temp_list[i]是小列表
    # 小列表里的元素都是字符串,表示的是该电影的类型
    # 它们放在loc的第二个位置,表示对多个位置同时赋值

print(zeros_df.head(3))

# 统计每个分类的电影的数量和
genre_count = zeros_df.sum(axis=0)  # 指定了折叠方向,返回的结果是Series类型
# print(genre_count)
# print(type(genre_count))

# 排序
genre_count = genre_count.sort_values()
# 因为是Series对象,因此无需指定排序字段,默认升序

_x = genre_count.index
_y = genre_count.values

# 画图
plt.figure(figsize=(20,8),dpi=80)
plt.bar(range(len(_x)),_y,width=0.4,color="orange")
plt.xticks(range(len(_x)),_x)
plt.show()

输出图像
在这里插入图片描述
字符串离散化,转化成数据进行统计,这个思路要学会。

2 数据合并

(1)join

默认情况下他是把行索引相同的数据合并到一起
在这里插入图片描述
没有数据的地方,用NaN补全

(2)merge

按照指定的列把数据按照一定的方式合并到一起
若t1和t2的数据如下所示
在这里插入图片描述
t1.merge(要连接的数据, left_on =左边关键字, right_on =右边关键字, how=连接方式)
在这里插入图片描述
可以看到,默认的合并方式为inner,即为交集

如果how为outer,则显示并集
在这里插入图片描述
没有数据的地方,用NaN补全

也可以以左边为准,或者右边为准
在这里插入图片描述
注意,所有情况都是在并集的基础上进行选择,也就是说,从并集里面选择特定的行显示,因此当以左边为主时,right_on不能省略,右边亦然

如果两个DataFrame对象,都有相同的字段(列),并希望以这相同的字段作为关键字进行连接,那么可以直接用on
在这里插入图片描述
在这里插入图片描述
on是左右两个数组都有的字段。左边有4列,右边有5列,但最后显示的结果只有8列,因为O已经合并

3 分组聚合

现在有一组关于全球星巴克店铺的统计数据(starbucks_store_worldwide.csv),如果想查看美国和中国的星巴克数量,该如何实现?

用以前学的方法,使用布尔索引

import pandas as pd
import numpy as np

file_path = "starbucks_store_worldwide.csv"
data = pd.read_csv("starbucks_store_worldwide.csv")

# print(data.info())
# print(data.head(1))

# 美国星巴克数量
info_us = data[data["Country"]=="US"]
print(len(info_us))

# 中国星巴克数量
info_cn = data[data["Country"]=="CN"]
print(len(info_cn))

输出

13608
2734

这里我们要介绍另外一种方法——分组聚合 groupby

(1)分组

使用Excel打开数据,可以看到有一个字段是Country,那么我们可以根据这个字段对数据进行分组,然后再筛选中国和美国的数据。
分组方法:df.groupby(by=字段名)
DataFrame对象调用groupby的结果是DataFrameGroupBy对象,它是可遍历的。
DataFrameGroupBy对象的每一个元素都是一个元组,元组里面是(索引(分组的值),分组之后的DataFrame),例如,将数据根据Country分组,那么其索引就是国家名。
Series对象调用groupby的结果是SeriesGroupBy对象,性质与DataFrameGroupBy对象类似,对Series对象进行分组聚合,在“3 复合索引”中会具体介绍。
分组示例:

import pandas as pd

dc = [{"city":"beijing", "brand":"puma", "tel":10086},
      {"city":"beijing", "brand":"nike", "tel":10010},
      {"city":"beijing", "brand":"addidas", "tel":10087},
      {"city":"shanghai", "brand":"puma", "tel":10011},
      {"city":"shanghai", "brand":"nike", "tel":10012},
      {"city":"shanghai", "brand":"addidas", "tel":10013}]

df = pd.DataFrame(dc)

# 遍历
grouped = df.groupby(by=["city"])
for i,j in grouped:
    print(i)
    print("-"*50)
    print(j,type(j))
    print("*"*80)

输出

beijing
--------------------------------------------------
      city    brand    tel
0  beijing     puma  10086
1  beijing     nike  10010
2  beijing  addidas  10087 <class 'pandas.core.frame.DataFrame'>
********************************************************************************
shanghai
--------------------------------------------------
       city    brand    tel
3  shanghai     puma  10011
4  shanghai     nike  10012
5  shanghai  addidas  10013 <class 'pandas.core.frame.DataFrame'>
********************************************************************************

(2)聚合

其实就是调用聚合方法,常用聚合方法如下:
在这里插入图片描述

(3)分组聚合

将星巴克店铺统计数据先按国家名(Country)进行分组,然后使用count()方法计算每个国家的数量,代码如下:

import pandas as pd
import numpy as np

file_path = "starbucks_store_worldwide.csv"

df = pd.read_csv(file_path)

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

# grouped是一个DataFrameGroupBy对象,是可迭代的
# grouped中的每一个元素是一个元组
# 元组里面是(索引(分组的值),分组之后的DataFrame)

# 遍历
# for i,j in grouped:   # i是索引,j是分组之后的DataFrame
#     print(i)
#     print("-"*100)
#     print(j,type(j))
#     print("*"*100)

# 调用聚合方法
print(grouped.count())  # 统计每一种分类的频数

输出

         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
Name: Brand, Length: 73, dtype: int64

数据聚合时若未指定列,则返回DataFrame型,若指定列则返回Series类型。
“分组聚合”(不是分组,也不是聚合,而是 分组+聚合)可以作用于Series和DataFrame,作用于Series则返回Series,作用于DataFrame则返回DataFrame。

print(type(grouped.count()))
print(type(grouped["Brand"].count()))

输出

<class 'pandas.core.frame.DataFrame'>
<class 'pandas.core.series.Series'>

现在使用聚合方法统计中国和美国的星巴克数量

import pandas as pd
import numpy as np

file_path = "starbucks_store_worldwide.csv"
df = pd.read_csv(file_path)
grouped = df.groupby(by="Country")

country_count = grouped["Brand"].count()
# 因为对某一列聚合后,返回的结果是Series类型,索引是国家简称
# 因此使用Series的方法来访问数据
print(country_count["CN"])		
print(country_count["US"])

输出

2734
13608

统计中国各个省份的数量

import pandas as pd
import numpy as np

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

# 先把中国的数据筛选出来
china_data = df[df["Country"] =="CN"]
# print(china_data)

# 以字段 State/Province 作为分类依据,然后筛选字段
grouped = china_data.groupby(by="State/Province").count()["Brand"]

print(grouped)

输出

State/Province
11    236
12     58
13     24
14      8
15      8
21     57
22     13
23     16
31    551
32    354
33    315
34     26
35     75
36     13
37     75
41     21
42     76
43     35
44    333
45     21
46     16
50     41
51    104
52      9
53     24
61     42
62      3
63      3
64      2
91    162
92     13
Name: Brand, dtype: int64

第一列是省份的数字编号

3 复合索引

(1)复合索引的产生

以两个字段作为分类依据,那么就会产生复合索引

import pandas as pd
import numpy as np

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

grouped = df["Brand"].groupby(by=[df["Country"],df["State/Province"]]).count()

# 下面这条语句无法进行分组,因为数据框中就没有"Country","State/Province"这两个字段
# grouped = df["Brand"].groupby(by=["Country","State/Province"]).count()

print(grouped)
print(type(grouped))

输出

Country  State/Province
AD       7                  1
AE       AJ                 2
         AZ                48
         DU                82
         FU                 2
                           ..
US       WV                25
         WY                23
VN       HN                 6
         SG                19
ZA       GT                 3
Name: Brand, Length: 545, dtype: int64
<class 'pandas.core.series.Series'>

上面是先筛选好字段,即只取“Brand”,返回的结果是用两个字段作为分类依据,最后生成的对象仍然为Series类型,只有最后一列才是数据,前两列都是索引

如果不先筛选字段,那么by后面的内容,可以不用加df,但最后得到的是DataFrame对象

import pandas as pd
import numpy as np

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

grouped = df.groupby(by=["Country","State/Province"]).count()
print(grouped)
print(type(grouped))

输出

                        Brand  Store Number  ...  Longitude  Latitude
Country State/Province                       ...                     
AD      7                   1             1  ...          1         1
AE      AJ                  2             2  ...          2         2
        AZ                 48            48  ...         48        48
        DU                 82            82  ...         82        82
        FU                  2             2  ...          2         2
...                       ...           ...  ...        ...       ...
US      WV                 25            25  ...         25        25
        WY                 23            23  ...         23        23
VN      HN                  6             6  ...          6         6
        SG                 19            19  ...         19        19
ZA      GT                  3             3  ...          3         3

[545 rows x 11 columns]
<class 'pandas.core.frame.DataFrame'>

注意,若先筛选字段,但使用了两个方框,那么返回的结果是是DataFrame,而非Series,因为在DataFrame取列时,使用两对方括号,结果就是DataFrame
在这里插入图片描述
“分组聚合”可以作用于Series和DataFrame,作用于Series则返回Series,作用于DataFrame则返回DataFrame

若对Series使用groupby方法,但分类依据有多个字段,那么必须加df
在这里插入图片描述

(2)查看复合索引

获取索引 df.index

import pandas as pd

dc = {"name":["zhangsan", "lisi", "wangwu"],
      "age":[25, 26, 27],
      "tel":[10086, 10010, 10000],
      "score":[90, 89, 95]}
df = pd.DataFrame(dc)
print(df)
print(50 * '*')
data = df.groupby(by=["age", "score"]).sum()
print(data)
print(data.index)

输出

       name  age    tel  score
0  zhangsan   25  10086     90
1      lisi   26  10010     89
2    wangwu   27  10000     95
**************************************************
             tel
age score       
25  90     10086
26  89     10010
27  95     10000
MultiIndex([(25, 90),
            (26, 89),
            (27, 95)],
           names=['age', 'score'])

MultiIndex表示符合索引

若是Series,复合索引同样如此

data = df["tel"].groupby(by=[df["age"], df["score"]]).sum()
print(data)
print(data.index)

输出

**************************************************
age  score
25   90       10086
26   89       10010
27   95       10000
Name: tel, dtype: int64
MultiIndex([(25, 90),
            (26, 89),
            (27, 95)],
           names=['age', 'score'])

(3)复合索引取数据

import pandas as pd

dc = [{"city":"beijing", "brand":"puma", "tel":10086},
      {"city":"beijing", "brand":"nike", "tel":10010},
      {"city":"beijing", "brand":"addidas", "tel":10087},
      {"city":"shanghai", "brand":"puma", "tel":10011},
      {"city":"shanghai", "brand":"nike", "tel":10012},
      {"city":"shanghai", "brand":"addidas", "tel":10013}]

df = pd.DataFrame(dc)
# print(df)

t1 = df.groupby(by=["city", "brand"]).sum()
# print(t1)
# print(type(t1))

t2 = t1["tel"]
# print(t2)
# print(type(t2))

t1是DataFrame对象,数据如下:

                    tel
city     brand         
beijing  addidas  10087
         nike     10010
         puma     10086
shanghai addidas  10013
         nike     10012
         puma     10011

t2是Series对象,数据如下:

city      brand  
beijing   addidas    10087
          nike       10010
          puma       10086
shanghai  addidas    10013
          nike       10012
          puma       10011
Name: tel, dtype: int64

对于t1,使用loc来提取数据,第一次以外层索引为参数,第二次以内层索引为参数

print(t1.loc["shanghai"])
print('_' * 50)
print(type(t1.loc["shanghai"]))
print('_' * 50)
print(t1.loc["shanghai"].loc["addidas"])
print('_' * 50)
print(type(t1.loc["shanghai"].loc["addidas"]))

输出

           tel
brand         
addidas  10013
nike     10012
puma     10011
__________________________________________________
<class 'pandas.core.frame.DataFrame'>
__________________________________________________
tel    10013
Name: addidas, dtype: int64
__________________________________________________
<class 'pandas.core.series.Series'>

对于t2,直接使用中括号

print(t2["beijing"])
print('_' * 50)
print(type(t2["beijing"]))
print('*' * 50)
print(t2["beijing", "puma"])
print('+' * 50)
print(type(t2["beijing", "puma"]))

输出


brand
addidas    10087
nike       10010
puma       10086
Name: tel, dtype: int64
__________________________________________________
<class 'pandas.core.series.Series'>
**************************************************
10086
++++++++++++++++++++++++++++++++++++++++++++++++++
<class 'numpy.int64'>

(4)交换内层索引和外层索引

假设t1是DataFrame对象,数据如下:

                    tel
city     brand         
beijing  addidas  10087
         nike     10010
         puma     10086
shanghai addidas  10013
         nike     10012
         puma     10011

t2是Series对象,数据如下:

city      brand  
beijing   addidas    10087
          nike       10010
          puma       10086
shanghai  addidas    10013
          nike       10012
          puma       10011
Name: tel, dtype: int64

现在只想取“nike”对应的值,该怎么办?
可以先对内外层索引进行交换,然后使用去外层索引的方式取“nike”
交换内外层索引,swaplevel()

s1 = t1.swaplevel()
s2 = t2.swaplevel()
print(s1)
print(50*'*')
print(type(s1))
print(50*'*')
print(s2)
print(50*'*')
print(type(s2)))

输出

                    tel
brand   city           
addidas beijing   10087
nike    beijing   10010
puma    beijing   10086
addidas shanghai  10013
nike    shanghai  10012
puma    shanghai  10011
**************************************************
<class 'pandas.core.frame.DataFrame'>
**************************************************
brand    city    
addidas  beijing     10087
nike     beijing     10010
puma     beijing     10086
addidas  shanghai    10013
nike     shanghai    10012
puma     shanghai    10011
Name: tel, dtype: int64
**************************************************
<class 'pandas.core.series.Series'

使用以下命令,即可查看“nike”的值

            tel
city           
beijing   10010
shanghai  10012
**************************************************
city
beijing     10010
shanghai    10012
Name: tel, dtype: int64

4 索引与字段

(1)查看索引与字段

df.index是查看索引,df.columns是查看字段
在这里插入图片描述

(2)修改索引与字段

给df.index和df.columns赋值,就是给索引与字段赋值
在这里插入图片描述

(3)按指定索引取行

在这里插入图片描述

t2.reindex([“p”, “m”]),p原来没有,m原来就有,所以在新的DataFrame中,p所在行为NaN
相当于从原来的数据框中取行。即该方法表示:原来有的就取出来,原来没有的,就用NaN表示

(4)设置某字段为索引

在这里插入图片描述
设置字段a为索引的时候,也可以保留字段a,drop等于True,表示在显示的表格里,保留字段a
在这里插入图片描述
以原DataFrame中a所在列为索引,这里需要注意的是,索引是可以重复的,但字段不行

(4)索引和字段重复

index是可迭代对象,也是可以重复的
行索引(索引)可以重复,但列索引(字段)重复会覆盖,如:

import pandas as pd

dc = {"name":["zhangsan", "lisi", "wangwu"],
      "age":[25, 26, 27],
      "tel":[10086, 10010, 10000],
      "score":[90, 89, 95],
      "score":[90, 89, 100]}
df = pd.DataFrame(dc)
print(df)

输出

       name  age    tel  score
0  zhangsan   25  10086     90
1      lisi   26  10010     89
2    wangwu   27  10000    100

score重复,列索引重复的时候,以最后的为准

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值