前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Pandas中的数据转换[细节]

Pandas中的数据转换[细节]

作者头像
@小森
发布2024-06-28 09:25:38
1030
发布2024-06-28 09:25:38
举报
文章被收录于专栏:xiaosenxiaosen
代码语言:javascript
复制
import pandas as pd
import numpy as np

一、⭐️apply函数应用

apply是一个自由度很高的函数
对于Series,它可以迭代每一列的值操作:
代码语言:javascript
复制
df = pd.read_csv('data/table.csv')
df.head()
代码语言:javascript
复制
df['Math'].apply(lambda x:str(x)+'!').head() #可以使用lambda表达式,也可以使用函数

💥对于DataFrame,它在默认axis=0下可以迭代每一个列操作:

代码语言:javascript
复制
# def test(x):
#     print(x)
#     return x
# df.apply(test)#axis=0
# df.apply(lambda x:x.apply(lambda x:str(x)+'!')).head() #这是一个稍显复杂的例子,有利于理解apply的功能
temp_data = df[["Height", "Weight", "Math"]]
# temp_data

# 生成一个表格,每列是原来列的最大值,最小值,以及均值

代码语言:javascript
复制
def transfor(x):
    # x是Series
    result = pd.Series()
    result["max"] = x.max()
    result["min"] = x.min()
    result["avg"] = x.mean()
    return result

temp_data.apply(transfor, axis=0)
# 按列来传入,一列就是一个x
代码语言:javascript
复制
def transfor(x):
    # x -> series
    bmi = x["Weight"]/(x["Height"]/100)**2
    x["bmi"] = bmi
    return x

temp_data.apply(transfor, axis=1)# BMI =  # apply

Pandas中的axis参数=0时,永远表示的是处理方向而不是聚合方向,当axis='index'或=0时,对列迭代对行聚合,行即为跨列,axis=1同理 💥

二、⭐️矢量化字符串

为什么要用str属性

文本数据也就是我们常说的字符串,Pandas 为 Series 提供了 str 属性,通过它可以方便的对每个元素进行操作。

代码语言:javascript
复制
index = pd.Index(data=["Tom", "Bob", "Mary", "James", "Andy", "Alice"], name="name")

data = {
    "age": [18, 30, np.nan, 40, np.nan, 30],
    "city": ["Bei Jing ", "Shang Hai ", "Guang Zhou", "Shen Zhen", np.nan, " "],
    "sex": [None, "male", "female", "male", np.nan, "unknown"],
    "birth": ["2000-02-10", "1988-10-17", None, "1978-08-08", np.nan, "1988-10-17"]
}

user_info = pd.DataFrame(data=data, index=index)

# 将出生日期转为时间戳
user_info["birth"] = pd.to_datetime(user_info.birth)
user_info

💯在对 Series 中每个元素处理时,我们可以使用apply 方法。

💯比如,我想要将每个城市都转为小写,可以使用如下的方式。

代码语言:javascript
复制
user_info.city.map(lambda x: x.lower())
AttributeError: 'float' object has no attribute 'lower'

💯错误原因是因为 float 类型的对象没有 lower 属性。这是因为缺失值(np.nan)属于float 类型。这时候我们的str属性操作来了,来看看如何使用吧~

代码语言:javascript
复制
# 将文本转为小写
user_info.city.str.lower()

可以看到,通过 `str` 属性来访问之后用到的方法名与 Python 内置的字符串的方法名一样。并且能够自动排除缺失值。我们再来试试其他一些方法。例如,统计每个字符串的长度。

代码语言:javascript
复制
user_info.city.str.len()
替换和分割

使用 .srt 属性也支持替换与分割操作。

先来看下替换操作,例如:将空字符串替换成下划线。

代码语言:javascript
复制
user_info.city.str.replace(" ", "_")

🏹replace 方法还支持正则表达式,例如将所有开头为 S 的城市替换为空字符串。

代码语言:javascript
复制
user_info.city.str.replace("^S.*", " ")

🏹再来看下分割操作,例如根据空字符串来分割某一列

代码语言:javascript
复制
user_info.city.str.split(" ")

🏹分割列表中的元素可以使用 get[] 符号进行访问:

代码语言:javascript
复制
user_info.city.str.split(" ").str.get(1)

🏹设置参数 expand=True 可以轻松扩展此项以返回 DataFrame。

代码语言:javascript
复制
user_info.city.str.split(" ", expand=True)
提取子串

既然是在操作字符串,很自然,你可能会想到是否可以从一个长的字符串中提取出子串。答案是可以的。

提取第一个匹配的子串

extract 方法接受一个正则表达式并至少包含一个捕获组,指定参数 expand=True 可以保证每次都返回 DataFrame。

例如,现在想要匹配空字符串前面的所有的字母,可以使用如下操作:

代码语言:javascript
复制
user_info.city.str.extract("(\w+)\s+", expand=True)

如果使用多个组提取正则表达式会返回一个 DataFrame,每个组只有一列。

例如,想要匹配出空字符串前面和后面的所有字母,操作如下:

代码语言:javascript
复制
user_info.city.str.extract("(\w+)\s+(\w+)", expand=True)
测试是否包含子串

除了可以匹配出子串外,我们还可以使用 contains 来测试是否包含子串。例如,想要测试城市是否包含子串 “Zh”。

代码语言:javascript
复制
user_info.city.str.contains("Zh")

当然了,正则表达式也是支持的。例如,想要测试是否是以字母 “S” 开头。

代码语言:javascript
复制
user_info.city.str.contains("^S")
生成哑变量

这是一个神奇的功能,通过 get_dummies 方法可以将字符串转为哑变量,sep 参数是指定哑变量之间的分隔符。来看看效果吧。

代码语言:javascript
复制
user_info.city.str.get_dummies(sep=" ")

这样,它提取出了 Bei, Guang, Hai, Jing, Shang, Shen, Zhen, Zhou 这些哑变量,并对每个变量下使用 0 或 1 来表达。实际上与 One-Hot(狂热编码)是一回事。

⭐️方法摘要

这里列出了一些常用的方法摘要。

方法

描述

cat()

连接字符串

split()

在分隔符上分割字符串

rsplit()

从字符串末尾开始分隔字符串

get()

索引到每个元素(检索第i个元素)

join()

使用分隔符在系列的每个元素中加入字符串

get_dummies()

在分隔符上分割字符串,返回虚拟变量的DataFrame

contains()

如果每个字符串都包含pattern / regex,则返回布尔数组

replace()

用其他字符串替换pattern / regex的出现

repeat()

重复值(s.str.repeat(3)等同于x * 3 t2 >)

pad()

将空格添加到字符串的左侧,右侧或两侧

center()

相当于str.center

ljust()

相当于str.ljust

rjust()

相当于str.rjust

zfill()

等同于str.zfill

wrap()

将长长的字符串拆分为长度小于给定宽度的行

slice()

切分Series中的每个字符串

slice_replace()

用传递的值替换每个字符串中的切片

count()

计数模式的发生

startswith()

相当于每个元素的str.startswith(pat)

endswith()

相当于每个元素的str.endswith(pat)

findall()

计算每个字符串的所有模式/正则表达式的列表

match()

在每个元素上调用re.match,返回匹配的组作为列表

extract()

在每个元素上调用re.search,为每个元素返回一行DataFrame,为每个正则表达式捕获组返回一列

extractall()

在每个元素上调用re.findall,为每个匹配返回一行DataFrame,为每个正则表达式捕获组返回一列

len()

计算字符串长度

strip()

相当于str.strip

rstrip()

相当于str.rstrip

lstrip()

相当于str.lstrip

partition()

等同于str.partition

rpartition()

等同于str.rpartition

lower()

相当于str.lower

upper()

相当于str.upper

find()

相当于str.find

rfind()

相当于str.rfind

index()

相当于str.index

rindex()

相当于str.rindex

capitalize()

相当于str.capitalize

swapcase()

相当于str.swapcase

normalize()

返回Unicode标准格式。相当于unicodedata.normalize

translate()

等同于str.translate

isalnum()

等同于str.isalnum

isalpha()

等同于str.isalpha

isdigit()

相当于str.isdigit

isspace()

等同于str.isspace

islower()

相当于str.islower

isupper()

相当于str.isupper

istitle()

相当于str.istitle

isnumeric()

相当于str.isnumeric

isdecimal()

相当于str.isdecimal

函数应用

虽说 Pandas 为我们提供了非常丰富的函数,有时候我们可能需要自己定制一些函数,并将它应用到 DataFrame 或 Series。常用到的函数有:mapapplyapplymap

map 是 Series 中特有的方法,通过它可以对 Series 中的每个元素实现转换。

如果我想通过年龄判断用户是否属于中年人(30岁以上为中年),通过 map 可以轻松搞定它。

代码语言:javascript
复制
# 接收一个 lambda 函数
user_info.age.map(lambda x: "yes" if x >= 30 else "no")

又比如,我想要通过城市来判断是南方还是北方,我可以这样操作

代码语言:javascript
复制
user_info.city

city_map = {
    "BeiJing": "north",
    "ShangHai": "south",
    "GuangZhou": "south",
    "ShenZhen": "south"
}

# 传入一个 map
user_info.city.str.replace(" ","").map(city_map)

apply 方法既支持 Series,也支持 DataFrame,在对 Series 操作时会作用到每个值上,在对 DataFrame 操作时会作用到所有行或所有列(通过 axis 参数控制)。

代码语言:javascript
复制
# 对 Series 来说,apply 方法 与 map 方法区别不大。
user_info.age.apply(lambda x: "yes" if x >= 30 else "no")

applymap 方法针对于 DataFrame,它作用于 DataFrame 中的每个元素,它对 DataFrame 的效果类似于 apply 对 Series 的效果。

大家如果感觉可以的话,可以去做一些小练习~~

【练习一】 现有一份关于字符串的数据集,请解决以下问题: (a)现对字符串编码存储人员信息(在编号后添加ID列),使用如下格式:“×××(名字):×国人,性别×,生于×年×月×日” (b)将(a)中的人员生日信息部分修改为用中文表示(如一九七四年十月二十三日),其余返回格式不变。 (c)将(b)中的ID列结果拆分为原列表相应的5列,并使用equals检验是否一致。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-06-27,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、⭐️apply函数应用
    • apply是一个自由度很高的函数
      • 对于Series,它可以迭代每一列的值操作:
      • 二、⭐️矢量化字符串
      • 为什么要用str属性
        • 替换和分割
          • 提取子串
            • 提取第一个匹配的子串
              • 测试是否包含子串
                • 生成哑变量
                • ⭐️方法摘要
                  • 函数应用
                  领券
                  问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档