展开
拓展 关闭
订阅号推广码
GitHub
视频
公告栏 关闭

Pandas基本使用(五):字符串函数/分组聚合

字符串函数

path = r"C:\work\python\pandas_files\字符串.xlsx"
data = pd.read_excel(path)
print(data)
output
          日期  工号   姓名  年龄  战斗力   温度    状态    里程    特常   地区             拼英
0 2020-05-01  21  丁智敏  37  200  36℃  满血激活   近距离  指鹿为马   丑国  ding zhi ming
1 2020-05-02  22  李平平  26  250  37℃  零血销毁   远距离  隔空取物   米国   li ping ping
2 2020-05-03  23   王松  27  200  38℃  满血激活   近距离  指鹿为马   丑国      wang song
3 2020-05-04  24  卢海军  34  200  39℃  零血销毁  中远距离  隔空取物   米国     lu hai jun
4 2020-05-05  25   王刚  38  250  40℃  零血销毁   远距离  指鹿为马   丑国      wang gang
5 2020-05-06  26  NaN  35  200  41℃   NaN   NaN   NaN  NaN            NaN
# 将所有姓名中的字符 丁,替换成字符 王
b = data.姓名.str.replace('丁', '王')
print(b)
output
0    王智敏
1    李平平
2     王松
3    卢海军
4     王刚
5    NaN
Name: 姓名, dtype: object
# 去掉温度后面的℃,并且转换为int
b = data.温度.str.replace('℃', '').astype('int')
print(b)
output
0    36
1    37
2    38
3    39
4    40
5    41
Name: 温度, dtype: int32
# 拼凑字符串,按照行拼凑
print(data[['温度', '姓名', '状态']])
b = data.温度+data.姓名+data.状态
print(b)
output
    温度   姓名    状态
0  36℃  丁智敏  满血激活
1  37℃  李平平  零血销毁
2  38℃   王松  满血激活
3  39℃  卢海军  零血销毁
4  40℃   王刚  零血销毁
5  41℃  NaN   NaN

0    36℃丁智敏满血激活
1    37℃李平平零血销毁
2     38℃王松满血激活
3    39℃卢海军零血销毁
4     40℃王刚零血销毁
5           NaN
dtype: object
# 拼凑一列字符串
b = data.姓名.str.cat()
print(b)
output
丁智敏李平平王松卢海军王刚
# 拼凑一列字符串,使用指定分隔符分隔
b = data.姓名.str.cat(sep=',')
print(b)
output
丁智敏,李平平,王松,卢海军,王刚
# 每个姓名的后面加上 六六六,注意:乘以记录的行数
b = data.姓名.str.cat(['六六六']*6)
print(b)
b = data.姓名.str.cat(['六六六']*len(data))
print(b)
# 直接加
b = data.姓名+'六六六'
print(b)
output
0    丁智敏六六六
1    李平平六六六
2     王松六六六
3    卢海军六六六
4     王刚六六六
5       NaN
Name: 姓名, dtype: object

0    丁智敏六六六
1    李平平六六六
2     王松六六六
3    卢海军六六六
4     王刚六六六
5       NaN
Name: 姓名, dtype: object

0    丁智敏六六六
1    李平平六六六
2     王松六六六
3    卢海军六六六
4     王刚六六六
5       NaN
Name: 姓名, dtype: object
# 每个姓名后面加上 aa 用 - 连接
# na_rep='无名':将NaN替换成指定的内容
b = data.姓名.str.cat(['六六六']*len(data), sep='-', na_rep='无名')
print(b)
output
0    丁智敏-六六六
1    李平平-六六六
2     王松-六六六
3    卢海军-六六六
4     王刚-六六六
5     无名-六六六
Name: 姓名, dtype: object
# 指定的分割字符会消失
# 默认
print(data.状态)
# 分割
b = data.状态.str.split('血')
print(b)
output
0    满血激活
1    零血销毁
2    满血激活
3    零血销毁
4    零血销毁
5     NaN
Name: 状态, dtype: object

0    [满, 激活]
1    [零, 销毁]
2    [满, 激活]
3    [零, 销毁]
4    [零, 销毁]
5        NaN
Name: 状态, dtype: object
# 拼接
b = data.状态.str.cat(['血aa血bb血dd']*len(data))
print(b)
# 指定拆分次数
c = b.str.split('血', n=2)
print(c)
# expand=True 拆分成多列
c = b.str.split('血', expand=True)
print(c)
output
0    满血激活血aa血bb血dd
1    零血销毁血aa血bb血dd
2    满血激活血aa血bb血dd
3    零血销毁血aa血bb血dd
4    零血销毁血aa血bb血dd
5              NaN
Name: 状态, dtype: object

0    [满, 激活, aa血bb血dd]
1    [零, 销毁, aa血bb血dd]
2    [满, 激活, aa血bb血dd]
3    [零, 销毁, aa血bb血dd]
4    [零, 销毁, aa血bb血dd]
5                  NaN
Name: 状态, dtype: object

     0    1    2    3    4
0    满   激活   aa   bb   dd
1    零   销毁   aa   bb   dd
2    满   激活   aa   bb   dd
3    零   销毁   aa   bb   dd
4    零   销毁   aa   bb   dd
5  NaN  NaN  NaN  NaN  NaN
# 将内容拆分成3列: 分割前,分割字符,分割后
# 默认
print(data.状态)
# 分割
b = data.状态.str.partition('血')
print(b)
# 拼接
b = data.状态.str.cat(['血aa血bb血dd']*len(data))
print(b)
# 分割
c = b.str.partition('血')
print(c)
output
0    满血激活
1    零血销毁
2    满血激活
3    零血销毁
4    零血销毁
5     NaN
Name: 状态, dtype: object

     0    1    2
0    满    血   激活
1    零    血   销毁
2    满    血   激活
3    零    血   销毁
4    零    血   销毁
5  NaN  NaN  NaN

0    满血激活血aa血bb血dd
1    零血销毁血aa血bb血dd
2    满血激活血aa血bb血dd
3    零血销毁血aa血bb血dd
4    零血销毁血aa血bb血dd
5              NaN
Name: 状态, dtype: object

     0    1            2
0    满    血  激活血aa血bb血dd
1    零    血  销毁血aa血bb血dd
2    满    血  激活血aa血bb血dd
3    零    血  销毁血aa血bb血dd
4    零    血  销毁血aa血bb血dd
5  NaN  NaN          NaN
# 默认
print(data.状态)
# 得到字符串下标为2的字符
b = data.状态.str.get(2)
print(b)
output
0    满血激活
1    零血销毁
2    满血激活
3    零血销毁
4    零血销毁
5     NaN
Name: 状态, dtype: object

0      激
1      销
2      激
3      销
4      销
5    NaN
Name: 状态, dtype: object
# 默认
print(data.状态)
# 切片
b = data.状态.str.slice(0, 3)
print(b)
b = data.状态.str[0:3]
print(b)
output
0    满血激活
1    零血销毁
2    满血激活
3    零血销毁
4    零血销毁
5     NaN
Name: 状态, dtype: object

0    满血激
1    零血销
2    满血激
3    零血销
4    零血销
5    NaN
Name: 状态, dtype: object

0    满血激
1    零血销
2    满血激
3    零血销
4    零血销
5    NaN
Name: 状态, dtype: object
# 默认
print(data.状态)
# 切片的内容替换成指定内容
b = data.状态.str.slice_replace(0, 3, 'aa')
print(b)
output
0    满血激活
1    零血销毁
2    满血激活
3    零血销毁
4    零血销毁
5     NaN
Name: 状态, dtype: object

0    aa活
1    aa毁
2    aa活
3    aa毁
4    aa毁
5    NaN
Name: 状态, dtype: object
# 默认
print(data.状态)
# 将字符串中的每一个字符串,用指定的字符串进行拼接
b = data.状态.str.join("-")
print(b)
output
0    满血激活
1    零血销毁
2    满血激活
3    零血销毁
4    零血销毁
5     NaN
Name: 状态, dtype: object

0    满-血-激-活
1    零-血-销-毁
2    满-血-激-活
3    零-血-销-毁
4    零-血-销-毁
5        NaN
Name: 状态, dtype: object
# 默认
print(data.状态)
# 查找字符串中是否包含指定字符,返回一个bool列表
b = data.状态.str.contains('满')
print(b)
output
0    满血激活
1    零血销毁
2    满血激活
3    零血销毁
4    零血销毁
5     NaN
Name: 状态, dtype: object

0     True
1    False
2     True
3    False
4    False
5      NaN
Name: 状态, dtype: object
# 默认
print(data.状态)
# 查找字符串中是否包含指定字符,返回一个bool列表,处理NaN
b = data.状态.str.contains('销', na=False)
print(data[b])
output
0    满血激活
1    零血销毁
2    满血激活
3    零血销毁
4    零血销毁
5     NaN
Name: 状态, dtype: object

          日期  工号   姓名  年龄  战斗力   温度    状态    里程    特常  地区            拼英
1 2020-05-02  22  李平平  26  250  37℃  零血销毁   远距离  隔空取物  米国  li ping ping
3 2020-05-04  24  卢海军  34  200  39℃  零血销毁  中远距离  隔空取物  米国    lu hai jun
4 2020-05-05  25   王刚  38  250  40℃  零血销毁   远距离  指鹿为马  丑国     wang gang
# 默认
print(data.状态)
# 查找字符串是否以 xx 开头
b = data.状态.str.startswith('满', na=False)
print(b)
output
0    满血激活
1    零血销毁
2    满血激活
3    零血销毁
4    零血销毁
5     NaN
Name: 状态, dtype: object

0     True
1    False
2     True
3    False
4    False
5    False
Name: 状态, dtype: bool
# 默认
print(data.状态)
# 查找字符串是否以 xx 结尾
b = data.状态.str.endswith('毁', na=False)
print(b)
output
0    满血激活
1    零血销毁
2    满血激活
3    零血销毁
4    零血销毁
5     NaN
Name: 状态, dtype: object

0    False
1     True
2    False
3     True
4     True
5    False
Name: 状态, dtype: bool
# 默认
print(data.状态)
# 复制3行
b = data.状态.repeat(3)
print(b)
# 将内容重复3次
b = data.状态*3
print(b)
output
0    满血激活
1    零血销毁
2    满血激活
3    零血销毁
4    零血销毁
5     NaN
Name: 状态, dtype: object

0    满血激活
0    满血激活
0    满血激活
1    零血销毁
1    零血销毁
1    零血销毁
2    满血激活
2    满血激活
2    满血激活
3    零血销毁
3    零血销毁
3    零血销毁
4    零血销毁
4    零血销毁
4    零血销毁
5     NaN
5     NaN
5     NaN
...
3    零血销毁零血销毁零血销毁
4    零血销毁零血销毁零血销毁
5             NaN
Name: 状态, dtype: object
# 默认
print(data.姓名)
# 用指定的字符填充到指定的长度
b = data.姓名.str.pad(5, fillchar='*')
print(b)
output
0    丁智敏
1    李平平
2     王松
3    卢海军
4     王刚
5    NaN
Name: 姓名, dtype: object

0    **丁智敏
1    **李平平
2    ***王松
3    **卢海军
4    ***王刚
5      NaN
Name: 姓名, dtype: object
# 默认
print(data.姓名)
# 用指定的字符填充到指定的长度,指定左右
# b = data.姓名.str.pad(5, fillchar='*', side='right')
b = data.姓名.str.pad(5, fillchar='*', side='both')
print(b)
output
0    丁智敏
1    李平平
2     王松
3    卢海军
4     王刚
5    NaN
Name: 姓名, dtype: object

0    *丁智敏*
1    *李平平*
2    **王松*
3    *卢海军*
4    **王刚*
5      NaN
Name: 姓名, dtype: object
# 默认
print(data.姓名)
# 填充0,可以用 pad 代替
b = data.姓名.str.zfill(5)
print(b)
output
0    丁智敏
1    李平平
2     王松
3    卢海军
4     王刚
5    NaN
Name: 姓名, dtype: object

0    00丁智敏
1    00李平平
2    000王松
3    00卢海军
4    000王刚
5      NaN
Name: 姓名, dtype: object
# 默认
print(data.里程)
# 去掉前后的指定字符
b = data.里程.str.strip('离中远')
print(b)
output
0     近距离
1     远距离
2     近距离
3    中远距离
4     远距离
5     NaN
Name: 里程, dtype: object

0     近距
1      距
2     近距
3      距
4      距
5    NaN
Name: 里程, dtype: object
# 去掉左边的指定字符
b = data.里程.str.lstrip('离中远')
print(b)
# 去掉右边的指定字符
b = data.里程.str.rstrip('离中远')
print(b)
output
0    近距离
1     距离
2    近距离
3     距离
4     距离
5    NaN
Name: 里程, dtype: object

0     近距
1     远距
2     近距
3    中远距
4     远距
5    NaN
Name: 里程, dtype: object
# 按照指定的内容进行替换,映射表中只能是单个字符
dic = str.maketrans({'距': 'ju', '离': 'li'})
b = data.里程.str.translate(dic)
print(b)
output
0     近juli
1     远juli
2     近juli
3    中远juli
4     远juli
5       NaN
Name: 里程, dtype: object
# 默认
print(data.日期)
# find() 查找指定字符串出现的位置,没有找到返回-1
# 注意:日期类型必须先转换为字符串
b = data.日期.astype('str').str.find('-')
print(b)
# 从指定位置开始查找
b = data.日期.astype('str').str.find('-', 5)
print(b)
output
0   2020-05-01
1   2020-05-02
2   2020-05-03
3   2020-05-04
4   2020-05-05
5   2020-05-06
Name: 日期, dtype: datetime64[ns]

0    4
1    4
2    4
3    4
4    4
5    4
Name: 日期, dtype: int64

0    7
1    7
2    7
3    7
4    7
5    7
Name: 日期, dtype: int64
# 默认
print(data.拼英)
# 将小写全部变成大写
b = data.拼英.str.upper()
print(b)
# 将大写变小写
b = data.拼英.str.lower().fillna('')
print(b)
# 首字母大写
b = data.拼英.str.title()
print(b)
# 第一个字母大写
b = data.拼英.str.capitalize()
print(b)
# 大小写交换
b = data.拼英.str.title()
print(b)
# 大小写交换
b = b.str.swapcase()
print(b)
# 判断是否全是字母
b = data.拼英.str.isalpha()
print(b)
output
0    ding zhi ming
1     li ping ping
2        wang song
3       lu hai jun
4        wang gang
5              NaN
Name: 拼英, dtype: object

0    DING ZHI MING
1     LI PING PING
2        WANG SONG
3       LU HAI JUN
4        WANG GANG
5              NaN
Name: 拼英, dtype: object

0    ding zhi ming
1     li ping ping
2        wang song
3       lu hai jun
4        wang gang
5                 
Name: 拼英, dtype: object

0    Ding Zhi Ming
1     Li Ping Ping
2        Wang Song
3       Lu Hai Jun
...
3    False
4    False
5      NaN
Name: 拼英, dtype: object
# 默认
print(data.工号)
# 判断是否全是数字
b = data.工号.astype('str').str.isnumeric()
print(b)
# 判断是否全是 字母+数字
b = data.工号.astype('str').str.isalnum()
print(b)
output
0    21
1    22
2    23
3    24
4    25
5    26
Name: 工号, dtype: int64

0    True
1    True
2    True
3    True
4    True
5    True
Name: 工号, dtype: bool

0    True
1    True
2    True
3    True
4    True
5    True
Name: 工号, dtype: bool
# 默认
print(data.状态)
# 正则表达式,符合条件则返回true
# .{2} :2个字符
b = data.状态.str.match('.{2}激')
print(b)
output
0    满血激活
1    零血销毁
2    满血激活
3    零血销毁
4    零血销毁
5     NaN
Name: 状态, dtype: object

0     True
1    False
2     True
3    False
4    False
5      NaN
Name: 状态, dtype: object
# 默认
print(data.日期)
# 正则
b = data.日期.astype('str').\
    str.extract('(\d{4})-(\d{2})-(\d{2})')
print(b)
# 替换
b = data.日期.astype('str').str.\
    replace('(\d{4})-(\d{2})-(\d{2})'
            ,r'\2月\3日\1年',regex=True)
print(b)
output
0   2020-05-01
1   2020-05-02
2   2020-05-03
3   2020-05-04
4   2020-05-05
5   2020-05-06
Name: 日期, dtype: datetime64[ns]

      0   1   2
0  2020  05  01
1  2020  05  02
2  2020  05  03
3  2020  05  04
4  2020  05  05
5  2020  05  06

0    05月01日2020年
1    05月02日2020年
2    05月03日2020年
3    05月04日2020年
4    05月05日2020年
5    05月06日2020年
Name: 日期, dtype: object

分组聚合

path = r"C:\work\python\pandas_files\分组聚合.xlsx"
data = pd.read_excel(path)
print(data)
output
    城市    区  人数  金额
0  北京市  西城区  37  74
1   天津  和平区  48  96
2  北京市  东城区  40  80
3   天津  南开区  34  68
4  北京市  西城区  49  98
5   天津  南开区  44  88
6   天津  和平区  49  98
7  北京市  东城区  48  96
8  北京市  西城区  26  52
9   天津  南开区  30  60
# 按照城市和区进行分组,求其他所有列分组后的和
b = data.groupby(['城市', '区']).sum()
print(b)
# 按照城市进行分组,求其他所有列分组后的和
b = data.groupby(['城市'])[['人数', '金额']].sum()
print(b)
output
          人数   金额
城市  区            
北京市 东城区   88  176
    西城区  112  224
天津  南开区  108  216
    和平区   97  194

      人数   金额
城市           
北京市  200  400
天津   205  410
'''
按照城市和地区分组
人数求和sum
金额求平均mean
'''
dic = {'人数': 'sum', '金额': 'mean'}
b = data.groupby(['城市', '区']).agg(dic)
print(b)
output
          人数         金额
城市  区                  
北京市 东城区   88  88.000000
    西城区  112  74.666667
天津  南开区  108  72.000000
    和平区   97  97.000000
path = r"C:\work\python\pandas_files\分组聚合2.xlsx"
data = pd.read_excel(path, index_col='店号')
print(data)
output
      1月  2月  3月  4月
店号                  
1店    25  77  76  29
1店    25  77  76  29
1店    25  77  76  29
2店    49  84  95  75
2店    49  84  95  75
25店   57  80  44  28
26店   58  81  45  29
27店   59  82  46  30
28店   60  83  47  31
35店   46  25  95  37
105店  57  84  95  37
225店  57  77  76  28
# 每个月用不同的函数进行统计
dic = {'1月': 'count', '2月': 'sum', '3月': 'max', '4月': 'min', }
# 分组
b = data.groupby('店号').agg(dic)
print(b)
output
      1月   2月  3月  4月
店号                   
105店   1   84  95  37
1店     3  231  76  29
225店   1   77  76  28
25店    1   80  44  28
26店    1   81  45  29
27店    1   82  46  30
28店    1   83  47  31
2店     2  168  95  75
35店    1   25  95  37
# 按照季度进行汇总,先按照季度汇总,再按照店汇总
dic = {'1月': '一季度', '2月': '一季度', '3月': '一季度',
       '4月': '二季度'}
b = data.groupby([dic], axis=1).sum()
print(b)
c = b.groupby('店号').sum()
print(c)
output
      一季度  二季度
店号            
1店    178   29
1店    178   29
1店    178   29
2店    228   75
2店    228   75
25店   181   28
26店   184   29
27店   187   30
28店   190   31
35店   166   37
105店  236   37
225店  210   28

      一季度  二季度
店号            
105店  236   37
1店    534   87
225店  210   28
25店   181   28
26店   184   29
27店   187   30
28店   190   31
2店    456  150
35店   166   37
# 按照季度进行汇总第二种,先店汇总,再季度
c = data.groupby('店号').sum()
print(c)
dic = {'1月': '一季度', '2月': '一季度', '3月': '一季度',
       '4月': '二季度'}
b = c.groupby([dic], axis=1).sum()
print(b)
output
      1月   2月   3月   4月
店号                     
105店  57   84   95   37
1店    75  231  228   87
225店  57   77   76   28
25店   57   80   44   28
26店   58   81   45   29
27店   59   82   46   30
28店   60   83   47   31
2店    98  168  190  150
35店   46   25   95   37

      一季度  二季度
店号            
105店  236   37
1店    534   87
225店  210   28
25店   181   28
26店   184   29
27店   187   30
28店   190   31
2店    456  150
35店   166   37
# 不使用 axis,使用 T 行列转换
b = data.groupby('店号').sum()
print(b.T)
dic = {'1月': '一季度', '2月': '一季度', '3月': '一季度',
       '4月': '二季度'}
c = b.T.groupby([dic]).sum().T
print(c)
output
店号  105店   1店  225店  25店  26店  27店  28店   2店  35店
1月    57   75    57   57   58   59   60   98   46
2月    84  231    77   80   81   82   83  168   25
3月    95  228    76   44   45   46   47  190   95
4月    37   87    28   28   29   30   31  150   37

      一季度  二季度
店号            
105店  236   37
1店    534   87
225店  210   28
25店   181   28
26店   184   29
27店   187   30
28店   190   31
2店    456  150
35店   166   37
path = r"C:\work\python\pandas_files\分组聚合3.xlsx"
data = pd.read_excel(path)
print(data)
output
   班级 性别  语文  数学
0  一班  男  55  68
1  一班  女  76  76
2  二班  男  51  65
3  二班  女  54  69
4  三班  男  50  78
5  三班  女  51  76
6  四班  男  80  67
7  四班  女  62  70
# 分组
b = data.groupby('班级')[['语文', '数学']].mean()
print(b)
output
      语文    数学
班级            
一班  65.5  72.0
三班  50.5  77.0
二班  52.5  67.0
四班  71.0  68.5
'''
将班级和性别做成索引列
index_col=[0,1]
如果两列作为索引列,使用下标[0,1],不能用列名
'''
path = r"C:\work\python\pandas_files\分组聚合3.xlsx"
data = pd.read_excel(path, index_col=[0, 1])
print(data)
output
       语文  数学
班级 性别        
一班 男   55  68
   女   76  76
二班 男   51  65
   女   54  69
三班 男   50  78
   女   51  76
四班 男   80  67
   女   62  70
# 按照班级分组,求所有列的平均
b = data.groupby('班级').mean()
print(b)
# 按照性别进行分组,求平均
b = data.groupby('性别').mean()
print(b)
# 按照班级和性别分组进行求和
b = data.groupby(['班级', '性别']).sum()
print(b)
# 单独对语文列使用班级进行求和
b = data['语文'].groupby('班级').sum()
print(b)
output
      语文    数学
班级            
一班  65.5  72.0
三班  50.5  77.0
二班  52.5  67.0
四班  71.0  68.5

       语文     数学
性别              
女   60.75  72.75
男   59.00  69.50

       语文  数学
班级 性别        
一班 女   76  76
   男   55  68
三班 女   51  76
   男   50  78
二班 女   54  69
   男   51  65
四班 女   62  70
   男   80  67

班级
一班    131
三班    101
二班    105
四班    142
Name: 语文, dtype: int64
"""
对多层索引进行分组
header=[0,1]
表示列表头,是前面两行
"""
path = r"C:\work\python\pandas_files\分组聚合4.xlsx"
data = pd.read_excel(path, header=[0, 1], index_col=0)
print(data.T)
output
        手机  电脑  平板  洗衣机  冰箱  电视
产品  名称                         
1季度 1月  36  28  34   35  20  28
    2月  29  28  43   22  50  20
    3月  35  49  42   48  28  47
2季度 4月  34  22  27   38  21  43
    5月  45  34  44   41  32  41
b = data.T.groupby(['产品']).sum().T
print(b)
output
产品   1季度  2季度
手机   100   79
电脑   105   56
平板   119   71
洗衣机  105   79
冰箱    98   53
电视    95   84
posted @ 2023-11-21 10:44  DogLeftover  阅读(19)  评论(0编辑  收藏  举报