如何操作文本数据
原文:
pandas.pydata.org/docs/getting_started/intro_tutorials/10_text_data.html
- 将所有名称字符改为小写。
In [4]: titanic["Name"].str.lower() Out[4]: 0 braund, mr. owen harris 1 cumings, mrs. john bradley (florence briggs th... 2 heikkinen, miss. laina 3 futrelle, mrs. jacques heath (lily may peel) 4 allen, mr. william henry ... 886 montvila, rev. juozas 887 graham, miss. margaret edith 888 johnston, miss. catherine helen "carrie" 889 behr, mr. karl howell 890 dooley, mr. patrick Name: Name, Length: 891, dtype: object
- 要使
Name
列中的每个字符串都变为小写,选择Name
列(参见数据选择教程),添加str
访问器并应用lower
方法。因此,每个字符串都被逐个转换。
与时间序列教程中具有dt
访问器的日期时间对象类似,在使用str
访问器时可以使用许多专门的字符串方法。这些方法通常与单个元素的内置字符串方法具有匹配的名称,但是在每个值的列上逐个应用(记得逐元素计算吗?)。
- 创建一个新列
Surname
,其中包含乘客的姓氏,通过提取逗号前的部分。
In [5]: titanic["Name"].str.split(",") Out[5]: 0 [Braund, Mr. Owen Harris] 1 [Cumings, Mrs. John Bradley (Florence Briggs ... 2 [Heikkinen, Miss. Laina] 3 [Futrelle, Mrs. Jacques Heath (Lily May Peel)] 4 [Allen, Mr. William Henry] ... 886 [Montvila, Rev. Juozas] 887 [Graham, Miss. Margaret Edith] 888 [Johnston, Miss. Catherine Helen "Carrie"] 889 [Behr, Mr. Karl Howell] 890 [Dooley, Mr. Patrick] Name: Name, Length: 891, dtype: object
- 使用
Series.str.split()
方法,每个值都返回一个包含 2 个元素的列表。第一个元素是逗号前的部分,第二个元素是逗号后的部分。
In [6]: titanic["Surname"] = titanic["Name"].str.split(",").str.get(0) In [7]: titanic["Surname"] Out[7]: 0 Braund 1 Cumings 2 Heikkinen 3 Futrelle 4 Allen ... 886 Montvila 887 Graham 888 Johnston 889 Behr 890 Dooley Name: Surname, Length: 891, dtype: object
- 由于我们只对代表姓氏的第一部分感兴趣(元素 0),我们可以再次使用
str
访问器,并应用Series.str.get()
来提取相关部分。事实上,这些字符串函数可以连接起来组合多个函数!
到用户指南
有关提取字符串部分的更多信息,请参阅用户指南中关于拆分和替换字符串的部分。
- 提取关于泰坦尼克号上女伯爵的乘客数据。
In [8]: titanic["Name"].str.contains("Countess") Out[8]: 0 False 1 False 2 False 3 False 4 False ... 886 False 887 False 888 False 889 False 890 False Name: Name, Length: 891, dtype: bool
In [9]: titanic[titanic["Name"].str.contains("Countess")] Out[9]: PassengerId Survived Pclass ... Cabin Embarked Surname 759 760 1 1 ... B77 S Rothes [1 rows x 13 columns]
- (对她的故事感兴趣吗?请参阅 维基百科!)
字符串方法Series.str.contains()
检查列Name
中的每个值是否包含单词Countess
,并对每个值返回True
(Countess
是名称的一部分)或False
(Countess
不是名称的一部分)。此输出可用于使用在数据子集教程中介绍的条件(布尔)索引来对数据进行子选择。由于泰坦尼克号上只有一位女伯爵,我们得到一行作为结果。
注意
字符串的更强大的提取操作是支持的,因为Series.str.contains()
和 Series.str.extract()
方法接受正则表达式,但不在本教程的范围内。
到用户指南
更多有关提取字符串部分的信息,请参阅用户指南中有关字符串匹配和提取的部分。
- 泰坦尼克号的乘客中,哪位乘客的名字最长?
In [10]: titanic["Name"].str.len() Out[10]: 0 23 1 51 2 22 3 44 4 24 .. 886 21 887 28 888 40 889 21 890 19 Name: Name, Length: 891, dtype: int64
- 要获得最长的名称,我们首先必须获取
Name
列中每个名称的长度。通过使用 pandas 字符串方法,对每个名称单独应用Series.str.len()
函数(逐元素)。
In [11]: titanic["Name"].str.len().idxmax() Out[11]: 307
- 接下来,我们需要获取对应位置,最好是表格中名字长度最大的索引标签。
idxmax()
方法正是这样做的。它不是字符串方法,适用于整数,因此不使用str
。
In [12]: titanic.loc[titanic["Name"].str.len().idxmax(), "Name"] Out[12]: 'Penasco y Castellana, Mrs. Victor de Satode (Maria Josefa Perez de Soto y Vallejo)'
- 基于行的索引名称(
307
)和列的名称(Name
),我们可以使用loc
运算符进行选择,该运算符在子集切片教程中介绍过。 - 在“性别”列中,将“male”的值替换为“M”,将“female”的值替换为“F”。
In [13]: titanic["Sex_short"] = titanic["Sex"].replace({"male": "M", "female": "F"}) In [14]: titanic["Sex_short"] Out[14]: 0 M 1 F 2 F 3 F 4 M .. 886 M 887 F 888 F 889 M 890 M Name: Sex_short, Length: 891, dtype: object
- 而
replace()
不是一个字符串方法,它提供了一种方便的方式来使用映射或词汇表来转换某些值。它需要一个dictionary
来定义映射{from : to}
。
警告
还有一个可用的replace()
方法,可以替换特定的字符集。但是,当有多个值的映射时,这将变得:
titanic["Sex_short"] = titanic["Sex"].str.replace("female", "F") titanic["Sex_short"] = titanic["Sex_short"].str.replace("male", "M")
这将变得繁琐,并且很容易出错。想想(或者试试)如果这两个语句以相反的顺序应用会发生什么…
记住
- 可以使用
str
访问器使用字符串方法。 - 字符串方法是逐元素进行的,可以用于条件索引。
replace
方法是根据给定字典转换值的便捷方法。
到用户指南
用户指南页面提供了处理文本数据的全面概述。
与其他工具的比较
原文:
pandas.pydata.org/docs/getting_started/comparison/index.html
- 与 R / R 库的比较
- 快速参考
- 基本 R
- plyr
- reshape / reshape2
- 与 SQL 的比较
- 复制 vs. 原地操作
- 选择
- WHERE
- GROUP BY
- 连接
- UNION
- 限制
- pandas 对一些 SQL 分析和聚合函数的等效操作
- 更新
- 删除
- 与电子表格的比较
- 数据结构
- 数据输入/输出
- 数据操作
- 字符串处理
- 合并
- 其他考虑因素
- 与 SAS 的比较
- 数据结构
- 数据输入/输出
- 数据操作
- 字符串处理
- 合并
- 缺失数据
- GroupBy
- 其他考虑因素
- 与 Stata 的比较
- 数据结构
- 数据输入/输出
- 数据操作
- 字符串处理
- 合并
- 缺失数据
- GroupBy
- 其他考虑因素
与 R/R 库的比较
译文:
pandas.pydata.org/docs/getting_started/comparison/comparison_with_r.html
由于 pandas 旨在提供许多人们使用R的数据操作和分析功能,因此本页面旨在更详细地查看R 语言及其许多第三方库与 pandas 的关系。在与 R 和 CRAN 库的比较中,我们关心以下几点:
- 功能性/灵活性:每个工具可以/不可以做什么
- 性能:操作有多快。最好提供硬性数据/基准
- 易用性:一个工具更容易/更难使用(您可能需要通过并排代码比较来判断)
本页面还提供了一个为这些 R 包的用户提供一点翻译指南的页面。
快速参考
我们将从一个快速参考指南开始,将一些常见的 R 操作(使用dplyr)与 pandas 的等效操作进行配对。
查询、过滤、抽样
R | pandas |
dim(df) |
df.shape |
head(df) |
df.head() |
slice(df, 1:10) |
df.iloc[:9] |
filter(df, col1 == 1, col2 == 1) |
df.query('col1 == 1 & col2 == 1') |
df[df$col1 == 1 & df$col2 == 1,] |
df[(df.col1 == 1) & (df.col2 == 1)] |
select(df, col1, col2) |
df[['col1', 'col2']] |
select(df, col1:col3) |
df.loc[:, 'col1':'col3'] |
select(df, -(col1:col3)) |
df.drop(cols_to_drop, axis=1) 但请参见[1] |
distinct(select(df, col1)) |
df[['col1']].drop_duplicates() |
distinct(select(df, col1, col2)) |
df[['col1', 'col2']].drop_duplicates() |
sample_n(df, 10) |
df.sample(n=10) |
sample_frac(df, 0.01) |
df.sample(frac=0.01) |
排序
R | pandas |
arrange(df, col1, col2) |
df.sort_values(['col1', 'col2']) |
arrange(df, desc(col1)) |
df.sort_values('col1', ascending=False) |
转换
R | pandas |
select(df, col_one = col1) |
df.rename(columns={'col1': 'col_one'})['col_one'] |
rename(df, col_one = col1) |
df.rename(columns={'col1': 'col_one'}) |
mutate(df, c=a-b) |
df.assign(c=df['a']-df['b']) |
分组和汇总
R | pandas |
summary(df) |
df.describe() |
gdf <- group_by(df, col1) |
gdf = df.groupby('col1') |
summarise(gdf, avg=mean(col1, na.rm=TRUE)) |
df.groupby('col1').agg({'col1': 'mean'}) |
summarise(gdf, total=sum(col1)) |
df.groupby('col1').sum() |
基础 R
使用 R 的c
进行切片
R 使得通过名称轻松访问 data.frame
列成为可能
df <- data.frame(a=rnorm(5), b=rnorm(5), c=rnorm(5), d=rnorm(5), e=rnorm(5)) df[, c("a", "c", "e")]
或按整数位置
df <- data.frame(matrix(rnorm(1000), ncol=100)) df[, c(1:10, 25:30, 40, 50:100)]
在 pandas 中按名称选择多列很简单
In [1]: df = pd.DataFrame(np.random.randn(10, 3), columns=list("abc")) In [2]: df[["a", "c"]] Out[2]: a c 0 0.469112 -1.509059 1 -1.135632 -0.173215 2 0.119209 -0.861849 3 -2.104569 1.071804 4 0.721555 -1.039575 5 0.271860 0.567020 6 0.276232 -0.673690 7 0.113648 0.524988 8 0.404705 -1.715002 9 -1.039268 -1.157892 In [3]: df.loc[:, ["a", "c"]] Out[3]: a c 0 0.469112 -1.509059 1 -1.135632 -0.173215 2 0.119209 -0.861849 3 -2.104569 1.071804 4 0.721555 -1.039575 5 0.271860 0.567020 6 0.276232 -0.673690 7 0.113648 0.524988 8 0.404705 -1.715002 9 -1.039268 -1.157892
通过整数位置选择多个不连续列可以通过iloc
索引器属性和numpy.r_
的组合实现。
In [4]: named = list("abcdefg") In [5]: n = 30 In [6]: columns = named + np.arange(len(named), n).tolist() In [7]: df = pd.DataFrame(np.random.randn(n, n), columns=columns) In [8]: df.iloc[:, np.r_[:10, 24:30]] Out[8]: a b c ... 27 28 29 0 -1.344312 0.844885 1.075770 ... 0.813850 0.132003 -0.827317 1 -0.076467 -1.187678 1.130127 ... 0.149748 -0.732339 0.687738 2 0.176444 0.403310 -0.154951 ... -0.493662 0.600178 0.274230 3 0.132885 -0.023688 2.410179 ... 0.109121 1.126203 -0.977349 4 1.474071 -0.064034 -1.282782 ... -0.858447 0.306996 -0.028665 .. ... ... ... ... ... ... ... 25 1.492125 -0.068190 0.681456 ... 0.428572 0.880609 0.487645 26 0.725238 0.624607 -0.141185 ... 1.008500 1.424017 0.717110 27 1.262419 1.950057 0.301038 ... 1.007824 2.826008 1.458383 28 -1.585746 -0.899734 0.921494 ... 0.577223 -1.088417 0.326687 29 -0.986248 0.169729 -1.158091 ... -2.013086 -1.602549 0.333109 [30 rows x 16 columns]
aggregate
在 R 中,您可能希望将数据拆分为子集并为每个子集计算平均值。使用名为df
的数据框,并将其拆分为by1
和by2
组:
df <- data.frame( v1 = c(1,3,5,7,8,3,5,NA,4,5,7,9), v2 = c(11,33,55,77,88,33,55,NA,44,55,77,99), by1 = c("red", "blue", 1, 2, NA, "big", 1, 2, "red", 1, NA, 12), by2 = c("wet", "dry", 99, 95, NA, "damp", 95, 99, "red", 99, NA, NA)) aggregate(x=df[, c("v1", "v2")], by=list(mydf2$by1, mydf2$by2), FUN = mean)
groupby()
方法类似于基本的 R aggregate
函数。
In [9]: df = pd.DataFrame( ...: { ...: "v1": [1, 3, 5, 7, 8, 3, 5, np.nan, 4, 5, 7, 9], ...: "v2": [11, 33, 55, 77, 88, 33, 55, np.nan, 44, 55, 77, 99], ...: "by1": ["red", "blue", 1, 2, np.nan, "big", 1, 2, "red", 1, np.nan, 12], ...: "by2": [ ...: "wet", ...: "dry", ...: 99, ...: 95, ...: np.nan, ...: "damp", ...: 95, ...: 99, ...: "red", ...: 99, ...: np.nan, ...: np.nan, ...: ], ...: } ...: ) ...: In [10]: g = df.groupby(["by1", "by2"]) In [11]: g[["v1", "v2"]].mean() Out[11]: v1 v2 by1 by2 1 95 5.0 55.0 99 5.0 55.0 2 95 7.0 77.0 99 NaN NaN big damp 3.0 33.0 blue dry 3.0 33.0 red red 4.0 44.0 wet 1.0 11.0
有关更多详细信息和示例,请参阅分组文档。
match
/ %in%
在 R 中选择数据的常见方法是使用%in%
,该运算符使用函数match
定义。运算符%in%
用于返回指示是否存在匹配项的逻辑向量:
s <- 0:4 s %in% c(2,4)
isin()
方法类似于 R 的%in%
运算符:
In [12]: s = pd.Series(np.arange(5), dtype=np.float32) In [13]: s.isin([2, 4]) Out[13]: 0 False 1 False 2 True 3 False 4 True dtype: bool
match
函数返回其第一个参数在第二个参数中匹配位置的向量:
s <- 0:4 match(s, c(2,4))
有关更多详细信息和示例,请参阅重塑文档。
tapply
tapply
类似于aggregate
,但数据可以是不规则的数组,因为子类大小可能不规则。使用名为baseball
的数据框,并根据数组team
检索信息:
baseball <- data.frame(team = gl(5, 5, labels = paste("Team", LETTERS[1:5])), player = sample(letters, 25), batting.average = runif(25, .200, .400)) tapply(baseball$batting.average, baseball.example$team, max)
在 pandas 中,我们可以使用pivot_table()
方法来处理这个问题:
In [14]: import random In [15]: import string In [16]: baseball = pd.DataFrame( ....: { ....: "team": ["team %d" % (x + 1) for x in range(5)] * 5, ....: "player": random.sample(list(string.ascii_lowercase), 25), ....: "batting avg": np.random.uniform(0.200, 0.400, 25), ....: } ....: ) ....: In [17]: baseball.pivot_table(values="batting avg", columns="team", aggfunc="max") Out[17]: team team 1 team 2 team 3 team 4 team 5 batting avg 0.352134 0.295327 0.397191 0.394457 0.396194
有关更多详细信息和示例,请参阅重塑文档。
subset
query()
方法类似于基本的 R subset
函数。在 R 中,您可能希望获取data.frame
的行,其中一列的值小于另一列的值:
df <- data.frame(a=rnorm(10), b=rnorm(10)) subset(df, a <= b) df[df$a <= df$b,] # note the comma
在 pandas 中,有几种方法可以执行子集。您可以使用query()
或将表达式传递为索引/切片,以及标准布尔索引:
In [18]: df = pd.DataFrame({"a": np.random.randn(10), "b": np.random.randn(10)}) In [19]: df.query("a <= b") Out[19]: a b 1 0.174950 0.552887 2 -0.023167 0.148084 3 -0.495291 -0.300218 4 -0.860736 0.197378 5 -1.134146 1.720780 7 -0.290098 0.083515 8 0.238636 0.946550 In [20]: df[df["a"] <= df["b"]] Out[20]: a b 1 0.174950 0.552887 2 -0.023167 0.148084 3 -0.495291 -0.300218 4 -0.860736 0.197378 5 -1.134146 1.720780 7 -0.290098 0.083515 8 0.238636 0.946550 In [21]: df.loc[df["a"] <= df["b"]] Out[21]: a b 1 0.174950 0.552887 2 -0.023167 0.148084 3 -0.495291 -0.300218 4 -0.860736 0.197378 5 -1.134146 1.720780 7 -0.290098 0.083515 8 0.238636 0.946550
有关更多详细信息和示例,请参阅查询文档。
with
在 R 中使用名为df
的数据框,其中包含a
和b
列的表达式将使用with
进行评估:
df <- data.frame(a=rnorm(10), b=rnorm(10)) with(df, a + b) df$a + df$b # same as the previous expression
在 pandas 中,使用eval()
方法的等效表达式将是:
In [22]: df = pd.DataFrame({"a": np.random.randn(10), "b": np.random.randn(10)}) In [23]: df.eval("a + b") Out[23]: 0 -0.091430 1 -2.483890 2 -0.252728 3 -0.626444 4 -0.261740 5 2.149503 6 -0.332214 7 0.799331 8 -2.377245 9 2.104677 dtype: float64 In [24]: df["a"] + df["b"] # same as the previous expression Out[24]: 0 -0.091430 1 -2.483890 2 -0.252728 3 -0.626444 4 -0.261740 5 2.149503 6 -0.332214 7 0.799331 8 -2.377245 9 2.104677 dtype: float64
在某些情况下,eval()
比纯 Python 中的评估要快得多。更多详细信息和示例请参见 eval 文档。
Pandas 2.2 中文官方教程和指南(三)(2)https://developer.aliyun.com/article/1509763