700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > 生成新的dataframe_Python之Pandas使用系列(九):DataFrame中列操作的技巧

生成新的dataframe_Python之Pandas使用系列(九):DataFrame中列操作的技巧

时间:2018-09-22 13:44:08

相关推荐

生成新的dataframe_Python之Pandas使用系列(九):DataFrame中列操作的技巧

介绍

本文将讨论使用iloc处理具有大量列的数据集的一些技巧和捷径。即使您有使用iloc的经验,也应该学习一些有用的技巧来加快自己的分析速度,并避免在代码中键入很多列名。

为什么我们关心选择列?

在许多标准数据科学示例中,列的数量相对较少。现实生活中的数据集很杂乱,通常包括很多额外的(可能是不必要的)列。

在数据科学问题中,由于以下一个或多个原因,您可能需要选择列的子集:

将数据过滤为仅包括相关列可以帮助减少内存占用并加快数据处理。限制列数可以减少将数据模型保留在头脑中的精神开销。探索新数据集时,可能有必要将任务分解为可管理的块。在某些情况下,您可能需要遍历各列并执行计算或清理,以便以所需的格式获取数据以进行进一步的分析。您的数据可能只包含不需要的额外或重复信息。

以下概述的技巧可以减少花费在整理数据列上的时间。

样例数据

为了说明一些示例,我将使用 Central Park Squirrel Census 数据集。对这个数据集中的松鼠进行计数和分类。

该数据集包括3023行数据和31列。尽管31列并不是很多列,但是它是一个有用的示例,可以说明您可能会应用到具有更多列的数据的概念。

如果您想继续阅读,可以查看jupyter notebook(/github/chris1610/pbpython/blob/master/notebooks/Selecting_Columns_in_DataFrame.ipynb

)或直接从github上将其拉出。

地址:/chris1610/pbpython/blob/master/notebooks/Selecting_Columns_in_DataFrame.ipynb

开始读取数据。

import pandas as pdimport numpy as npdf = pd.read_csv( 'https://data.cityofnewyork.us/api/views/vfnx-vebw/rows.csv?accessType=DOWNLOAD&bom=true&format=true')

有时记住每个列名及其在索引中的位置会很麻烦。这是一个简单的 list comprehension,可以建立所有列及其索引的参考列表。

col_mapping = [f"{c[0]}:{c[1]}" for in cenumerate(df.columns)]

这将创建一个像这样的列表:

['0:X','1:Y','2:Unique Squirrel ID','3:Hectare','4:Shift','5:Date', ...'33:Borough Boundaries','34:City Council Districts','35:Police Precincts']

在某些情况下,如果您想重命名一堆列,则可以使用dictionary comprehension 来创建数据的字典视图:

col_mapping_dict = {[0]:[1] ccfor in cenumerate(df.columns)}

创建了这个字典:

{0: 'X',1: 'Y',2: 'Unique Squirrel ID',3: 'Hectare',4: 'Shift',5: 'Date',...33: 'Borough Boundaries',34: 'City Council Districts',35: 'Police Precincts'}

定义这些变量在您进行分析时可能会很有用。无需反复查看原始文件,您只需在分析期间仔细检查变量名即可。

我经常要做的另一项常见任务是重命名一堆在文件中不一致命名的列。我使用字典来轻松地使用df.rename(columns = col_mapping)之类的名称来重命名所有列。键入所有列名称可能是容易出错的任务。一个简单的技巧是复制excel中的所有列,并使用pd.read_clipboard()构建一个小的DataFrame并将列转换为字典。然后,如果需要,我可以手动输入新名称。

这是此数据集的一个简单示例:

df_cols = pd.read_clipboard()col_mapping = {[1]:'' cfor in cenumerate(df_cols.columns)}

这将创建一个相对容易用新名称填充的字典:

{'X': '','Y': '','Unique': '','Squirrel': '','ID': '','Hectare': '','Shift': '',...'Police': '','Precincts': ''}

另外,您甚至可以使用Excel文件设置列重命名并自动完成整个过程。

使用iloc

我们将介绍的主要功能是Pandas的iloc,它用于基于整数位置的索引。新用户可能会有些困惑,因为iloc和loc可以采用布尔数组,这会导致更强大的索引编制。由于两个函数都可以将布尔数组作为输入,因此有时这些函数会产生相同的输出。这里我们将只关注iloc列的选择。

这是一个简单的图形,用于说明iloc的主要用法:

例如,如果您只想查看所有行的数据的Squirrel ID列:

df.iloc[:, 2]

0 37F-PM-1014-031 37E-PM-1006-032 2E-AM-1010-033 5D-PM-1018-054 39B-AM-1018-01 ...3018 30B-AM-1007-043019 19A-PM-1013-053020 22D-PM-1012-073021 29B-PM-1010-023022 5E-PM-1012-01Name: Unique Squirrel ID, Length: 3023, dtype: object

如果要查看X和Y的位置以及ID,可以传入整数[0,1,2]的列表:

df.iloc[:, [0,1,2]]

3023行×3列

键入所有列并不是最有效的方法,因此我们可以使用切片符号使它更容易理解:

df.iloc[:, 0:3]

它将产生与上述相同的输出。

如果您有一些使用python list的经验,并且曾经使用过pandas;所有这些用法都应该有意义。这些是panas基础的概念,但我们将从这里开始。

虽然这两种方法都很简单,但是如果要将整数列表与切片符号结合起来怎么办?您可以尝试如下操作:

df.iloc[:, [0:3,15:19]]

或者,您可以尝试执行以下操作:

df.iloc[:, 0:3,15:19]

IndexingError: Too many indexers

嗯 这显然不起作用,但似乎对于选择范围以及单个列很有用。

幸运的是,有一个numpy对象可以帮助我们。r_ 对象将“沿第一个轴将切片对象转换为串联对象。”由于从文档中获取的内容可能并不多,但它确实满足了我们的需求。

这是一个稍微复杂的示例,以显示它如何在单个列表项和切片范围的组合上工作:

np.r_[0:3,15:19,24,25]

array([ 0, 1, 2, 15, 16, 17, 18, 24, 25])

ok,该对象已将整数列表和切片符号的组合转换为单个列表,我们可以将其传递给iloc:

df.iloc[:, np.r_[0:3,15:19,24,25]]

3023行×20列

这是另一个提示。在使用read_csv读取数据时,您也可以使用此表示法:

df_2 = pd.read_csv( 'https://data.cityofnewyork.us/api/views/vfnx-vebw/rows.csv?accessType=DOWNLOAD&bom=true&format=true', usecols=np.r_[1,2,5:8,15:30],)

当您有一个要保留非连续列并且不想键入所有列的全名的数据集时,我觉得此符号很有用。

我要警告的一点是,在使用分片符号时您需要小心,并请记住,范围中的最后一个数字将不包含在生成的数字列表中。

例如,如果我们指定范围2:4,我们只会得到2和3的列表:

np.r_[2:4]

array([2, 3])

如果要包括列索引4,请使用np.r_ [2:5]。

关于np.r_的最后一条评论是,有一个可选的step参数。在此示例中,我们可以指定此列表将增加2:

np.r_[2:10:2]

array([2, 4, 6, 8])

这是一个更高级的选项,对于新的Pandas用户来说在直观上不会是显而易见的。但是,如果您发现自己通过索引解析了很多列,这回事一个有用的工具。

iloc和布尔数组

过滤列的最强大方法之一是将布尔数组传递给iloc以选择列的子集。这听起来有些复杂,但是有几个示例应该可以使此理解。

最重要的概念是我们不会手动生成布尔数组,而是使用另一个pandas函数的输出来生成数组并将其提供给iloc。

在这种情况下,我们可以在列索引上使用str访问器,就像其他任何pandas数据列一样。这将生成iloc期望的必要布尔数组。一个例子应该有助于使这一点变得清楚。

如果我们想查看哪些列包含单词“ run”:

run_cols = df.columns.str.contains('run', case=False)print(run_cols)

array([False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, True, False, False, False, False, False, False, False])

然后,我们可以传递此新的布尔值数组以仅选择两列:

df.iloc[:, run_cols].head()

在实践中,许多人将使用lambda函数来一行执行此操作:

df.iloc[:, lambda df:df.columns.str.contains('run', case=False)]

使用str函数的好处是,您可以使用潜在的过滤器选项来使其变得复杂。例如,如果我们希望所有名称中带有“ district”,“ precinct”或“ boundaries”的列:

df.iloc[:, lambda df: df.columns.str.contains('district|precinct|boundaries', case=False)].head()

我们甚至可以通过使用布尔数组的结果来获取索引,然后使用np.r_将这些列表组合在一起,从而将所有这些概念组合在一起。

这是一个示例,我们希望将所有与位置相关的列以及ID都放入DataFrame中:

location_cols = df.columns.str.contains('district|precinct|boundaries', case=False)location_indices = [ ifor , icol in enumerate(location_cols) if col]df.iloc[:, np.r_[0:3,location_indices]].head()

这段代码有点复杂,因为我们使用的是条件列表理解功能,对于选择7列可能会显得过分杀伤力。

注意事项

处理列的数字索引时要记住的一项内容是,您需要了解数据的来源。如果您希望ID列始终位于特定位置,并且它会更改数据的顺序,则可能会在后续数据处理中遇到问题。在这种情况下,您的领域知识和专业技能将发挥作用,以确保解决方案在给定情况下足够强大。

总结

大部分的数据分析工作都涉及在行级别过滤和选择数据。但是,有时以列方式处理数据会有所帮助。Pandas iloc是快速有效地处理包含多列数据的数据集的有用工具。我希望本文提供了一些技巧,可以帮助您进行自己的分析。

译自:/selecting-columns.html

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。