如何在 pandas 中获取数据帧的列切片

How to take column-slices of dataframe in pandas

提问人:cpa 提问时间:5/19/2012 最后编辑:Georgycpa 更新时间:10/26/2021 访问量:671034

问:

我从 CSV 文件加载一些机器学习数据。前 2 列是观测值,其余列是要素。

目前,我做以下工作:

data = pandas.read_csv('mydata.csv')

它给出了类似的东西:

data = pandas.DataFrame(np.random.rand(10,5), columns = list('abcde'))

我想将此数据帧切分为两个数据帧:一个包含列,另一个包含列,和 。abcde

不可能写这样的东西

observations = data[:'c']
features = data['c':]

我不确定最好的方法是什么。我需要一个吗?pd.Panel

顺便说一句,我发现数据帧索引非常不一致:是允许的,但不是。另一方面,是不允许的,但却是。 这有什么实际原因吗?如果列被 Int 索引,这真的很令人困惑,因为data['a']data[0]data['a':]data[0:]data[0] != data[0:1]

Python 熊猫 numpy 数据帧 切片

评论

4赞 Wes McKinney 5/20/2012
当你做 df[...] 时,DataFrame 本质上是一个类似 dict 的对象,但是有一些便利,例如 添加了用于选择行 (pandas.pydata.org/pandas-docs/stable/...df[5:10])
1赞 cpa 5/20/2012
那么,这种不一致是什么有利于便利性的设计决策呢?好吧,但对于初学者来说,它肯定需要更明确!
3赞 Yu Shen 1/5/2014
支持便利性的设计考虑使学习曲线更加陡峭。我希望一开始有更好的文档,只是提供一个一致的界面。例如,只关注 ix 接口。

答:

27赞 Brendan Wood 5/19/2012 #1

您可以通过引用列表中每列的名称来切片 a 的列,如下所示:DataFrame

data = pandas.DataFrame(np.random.rand(10,5), columns = list('abcde'))
data_ab = data[list('ab')]
data_cde = data[list('cde')]

评论

0赞 cpa 5/19/2012
因此,如果我想要从“b”列开始的所有数据,我需要在data.columns中找到“b”的索引并执行data[data.columns[1:]]?这就是规范的操作方式吗?
1赞 Brendan Wood 5/20/2012
您的意思是要从“b”开始选择所有列?
0赞 cpa 5/20/2012
是,或者选择给定范围内的所有列。
1赞 Brendan Wood 5/20/2012
我自己对熊猫很陌生,所以我不能说什么是规范的。我会像你说的那样做,但使用函数 on 来确定列“b”或其他什么的索引。get_locdata.columns
152赞 Karmel 5/21/2012 #2

注意:自 Pandas v0.20 起已弃用。应根据需要改用 或 。.ix.loc.iloc

DataFrame.ix 索引是您要访问的内容。这有点令人困惑(我同意 Pandas 索引有时令人困惑!),但以下内容似乎可以满足您的需求:

>>> df = DataFrame(np.random.rand(4,5), columns = list('abcde'))
>>> df.ix[:,'b':]
      b         c         d         e
0  0.418762  0.042369  0.869203  0.972314
1  0.991058  0.510228  0.594784  0.534366
2  0.407472  0.259811  0.396664  0.894202
3  0.726168  0.139531  0.324932  0.906575

其中 .ix[行切片,列切片] 是正在解释的内容。有关 Pandas 索引的更多信息,请访问:http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-advanced

评论

5赞 grasshopper 11/1/2013
注意熊猫的范围包括两个端点,即>>>data.ix[:, 'a':'c'] a b c 0 0.859192 0.881433 0.843624 1 0.744979 0.427986 0.177159
21赞 user602599 4/11/2014
多列驾驶室可以像这样通过df.ix[:,[0,3,4]]
3赞 ChaimG 7/2/2015
@Karmel:上面的输出中似乎存在复制/粘贴错误。也许你的意思是?df.ix[:,'b':'e']
6赞 John Zwinck 3/6/2017
最好使用:stackoverflow.com/a/31593712/4323locix
6赞 Ted Petrou 6/24/2017
像这样的旧答案需要删除。.ix 已弃用,不应使用。
42赞 moldovean 2/25/2014 #3

此外,给定一个 DataFrame

数据

如上例所示,如果您只想提取 A 列和 D 列(例如第 1 列和第 4 列),则需要从 Pandas DataFrame 中提取 iloc Mothod,并且可以非常有效地使用。您需要知道的只是要提取的列的索引。例如:

>>> data.iloc[:,[0,3]]

会给你

          a         d
0  0.883283  0.100975
1  0.614313  0.221731
2  0.438963  0.224361
3  0.466078  0.703347
4  0.955285  0.114033
5  0.268443  0.416996
6  0.613241  0.327548
7  0.370784  0.359159
8  0.692708  0.659410
9  0.806624  0.875476
24赞 user2023507 10/12/2014 #4

如果你来这里寻找切片两个范围的列并将它们组合在一起(像我一样),你可以做一些类似的事情

op = df[list(df.columns[0:899]) + list(df.columns[3593:])]
print op

这将创建一个新数据框,其中包含前 900 列和(所有)列> 3593(假设您的数据集中有大约 4000 列)。

评论

0赞 zwep 2/27/2019
太好了,有人试过了......我想知道,这个 0:899 获得了前 900 列。.他们为什么要这样做?这根本不像 Python。在 python 中使用范围时,它始终是“直到”而不是“直到并包含”
95赞 Shankar ARUL 11/30/2015 #5

让我们以 seaborn 包裹中的泰坦尼克号数据集为例

# Load dataset (pip install seaborn)
>> import seaborn.apionly as sns
>> titanic = sns.load_dataset('titanic')

使用列名

>> titanic.loc[:,['sex','age','fare']]

使用列索引

>> titanic.iloc[:,[2,3,6]]

using ix (早于 Pandas <.20 版本)

>> titanic.ix[:,[‘sex’,’age’,’fare’]]

>> titanic.ix[:,[2,3,6]]

使用 reindex 方法

>> titanic.reindex(columns=['sex','age','fare'])

评论

6赞 Shihe Zhang 9/5/2017
在 pandas 0.20 中:已弃用。.ix
0赞 Marc Maxmeister 1/9/2020
弃用警告:当您使用Passing list-likes to .loc or [] with any missing label will raise KeyError in the future, you can use .reindex() as an alternative.df.loc[:, some_list_of_columns]
22赞 Surya 6/20/2017 #6

以下是如何使用不同的方法进行选择性列切片,包括基于选择性标签、基于索引和基于选择性范围的列切片。

In [37]: import pandas as pd    
In [38]: import numpy as np
In [43]: df = pd.DataFrame(np.random.rand(4,7), columns = list('abcdefg'))

In [44]: df
Out[44]: 
          a         b         c         d         e         f         g
0  0.409038  0.745497  0.890767  0.945890  0.014655  0.458070  0.786633
1  0.570642  0.181552  0.794599  0.036340  0.907011  0.655237  0.735268
2  0.568440  0.501638  0.186635  0.441445  0.703312  0.187447  0.604305
3  0.679125  0.642817  0.697628  0.391686  0.698381  0.936899  0.101806

In [45]: df.loc[:, ["a", "b", "c"]] ## label based selective column slicing 
Out[45]: 
          a         b         c
0  0.409038  0.745497  0.890767
1  0.570642  0.181552  0.794599
2  0.568440  0.501638  0.186635
3  0.679125  0.642817  0.697628

In [46]: df.loc[:, "a":"c"] ## label based column ranges slicing 
Out[46]: 
          a         b         c
0  0.409038  0.745497  0.890767
1  0.570642  0.181552  0.794599
2  0.568440  0.501638  0.186635
3  0.679125  0.642817  0.697628

In [47]: df.iloc[:, 0:3] ## index based column ranges slicing 
Out[47]: 
          a         b         c
0  0.409038  0.745497  0.890767
1  0.570642  0.181552  0.794599
2  0.568440  0.501638  0.186635
3  0.679125  0.642817  0.697628

### with 2 different column ranges, index based slicing: 
In [49]: df[df.columns[0:1].tolist() + df.columns[1:3].tolist()]
Out[49]: 
          a         b         c
0  0.409038  0.745497  0.890767
1  0.570642  0.181552  0.794599
2  0.568440  0.501638  0.186635
3  0.679125  0.642817  0.697628

评论

0赞 Sᴀᴍ Onᴇᴌᴀ 6/20/2017
请尽量避免将代码作为答案,并尝试解释它的作用和原因。对于没有相关编码经验的人来说,您的代码可能并不明显。请编辑您的答案以包括澄清、上下文,并尝试在您的答案中提及任何限制、假设或简化。
318赞 Ted Petrou 6/24/2017 #7

2017 年答案 - pandas 0.20:.ix 已弃用。使用 .loc

请参阅文档中的弃用

.loc使用基于标签的索引来选择行和列。标签是索引或列的值。切片包含最后一个元素。.loc

假设我们有一个包含以下列的 DataFrame:
、、、、。
foobarquzantcatsatdat

# selects all rows and all columns beginning at 'foo' up to and including 'sat'
df.loc[:, 'foo':'sat']
# foo bar quz ant cat sat

.loc接受 Python 列表对行和列执行的相同切片表示法。切片表示法是start:stop:step

# slice from 'foo' to 'cat' by every 2nd column
df.loc[:, 'foo':'cat':2]
# foo quz cat

# slice from the beginning to 'bar'
df.loc[:, :'bar']
# foo bar

# slice from 'quz' to the end by 3
df.loc[:, 'quz'::3]
# quz sat

# attempt from 'sat' to 'bar'
df.loc[:, 'sat':'bar']
# no columns returned

# slice from 'sat' to 'bar'
df.loc[:, 'sat':'bar':-1]
sat cat ant quz bar

# slice notation is syntatic sugar for the slice function
# slice from 'quz' to the end by 2 with slice function
df.loc[:, slice('quz',None, 2)]
# quz cat dat

# select specific columns with a list
# select columns foo, bar and dat
df.loc[:, ['foo','bar','dat']]
# foo bar dat

您可以按行和列进行切片。例如,如果您有 5 行带有标签 、 、 、vwxyz

# slice from 'w' to 'y' and 'foo' to 'ant' by 3
df.loc['w':'y', 'foo':'ant':3]
#    foo ant
# w
# x
# y

评论

0赞 pashute 11/8/2017
如果您使用 apply 和 lambda 行,如: 那么您可以在 ...用。例如(根据这个 StackOverflow 答案),在 如果其中任何一个是非数字的,您可以估值:df['newcol'] = df.apply(lambda row: myfunc(row), axis=1)myfunc(row){row['foo':'ant']myfuncrow['foo':'ant'].apply(lambda x: isinstance(x, str)).any()
6赞 craned 7/1/2018
.iloc现在应该使用,而不是 .解决这个问题,我会投赞成票。.loc
2赞 brian_ds 4/17/2020
@craned - 这是不正确的。来自 Pandas 文档:.loc 主要基于标签,但也可以与布尔数组一起使用。.loc 将在找不到项目时引发 KeyError。关于.iloc也有类似的声明,除了它特指基于索引的切片。换句话说,在这个例子中,他使用了基于标签的索引,而 .loc 是正确的选择(基本上是唯一的选择)。例如,如果要按位置 -rows 5:10 进行切片,请使用 .iloc
1赞 John Smith 1/5/2021
如果我们想要,['foo', 'ant', 'cat', 'sat', 'dat'],没有 bar 和 quz,可以做这样的事情:['foo', 'ant': 'dat'],最快的方法是什么?
2赞 Max Kleiner 7/5/2018 #8

它的等价物

 >>> print(df2.loc[140:160,['Relevance','Title']])
 >>> print(df2.ix[140:160,[3,7]])
0赞 Vladimir Gavrysh 8/9/2018 #9

如果数据框如下所示:

group         name      count
fruit         apple     90
fruit         banana    150
fruit         orange    130
vegetable     broccoli  80
vegetable     kale      70
vegetable     lettuce   125

和 OUTPUT 可以是

   group    name  count
0  fruit   apple     90
1  fruit  banana    150
2  fruit  orange    130

如果使用逻辑运算符np.logical_not

df[np.logical_not(df['group'] == 'vegetable')]

更多信息

https://docs.scipy.org/doc/numpy-1.13.0/reference/routines.logic.html

其他逻辑运算符

  1. logical_and(x1, x2, /[, out, where, ...])计算 x1 和 x2 元素。

  2. logical_or(x1, x2, /[, out, where, casting, ...])逐个元素计算 x1 或 x2 的真值。

  3. logical_not(x, /[, out, where, casting, ...])计算真相 NOT x 元素的值。
  4. logical_xor(x1, x2, /[, out, where, ..])计算 x1 XOR x2 的真值,逐个元素。
3赞 Camilo 7/10/2019 #10

假设您想要所有行,则从 DataFrame 中获取列子集的另一种方法是:
如果
要使用数字列索引,可以执行以下操作:
data[['a','b']]data[['c','d','e']]data[data.columns[:2]]data[data.columns[2:]]

0赞 Mykola Zotko 10/26/2021 #11

您可以使用截断方法

df = pd.DataFrame(np.random.rand(10, 5), columns = list('abcde'))

df_ab = df.truncate(before='a', after='b', axis=1)
df_cde = df.truncate(before='c', axis=1)