选择/排除pandas中的列集

Ame*_*ina 244 python dataframe pandas

我想根据列选择从现有数据框创建视图或数据框.

例如,我想df2从数据框创建一个数据框,该数据框df1包含除其中两个列之外的所有列.我尝试了以下操作,但它不起作用:

import numpy as np
import pandas as pd

# Create a dataframe with columns A,B,C and D
df = pd.DataFrame(np.random.randn(100, 4), columns=list('ABCD'))

# Try to create a second dataframe df2 from df with all columns except 'B' and D
my_cols = set(df.columns)
my_cols.remove('B').remove('D')

# This returns an error ("unhashable type: set")
df2 = df[my_cols]
Run Code Online (Sandbox Code Playgroud)

我究竟做错了什么?也许更一般地说,大熊猫有哪些机制支持从数据框中挑选和排除任意列的列?

Amr*_*ant 338

您可以删除不需要的列或选择您需要的列

# Using DataFrame.drop
df.drop(df.columns[[1, 2]], axis=1, inplace=True)

# drop by Name
df1 = df1.drop(['B', 'C'], axis=1)

# Select the ones you want
df1 = df[['a','d']]
Run Code Online (Sandbox Code Playgroud)

  • @ 3kstc你可以使用`df1.iloc [:,[ - 1]]`这将选择所有行,最后一列. (5认同)
  • 有没有办法只选择第 n 列?即:`df1 = my_df[[n]]` 其中 _n_ 是 _n_ 列数的最后一列,我正在尝试负索引 `[[-1]]`<- 它不起作用:( 帮助!~ (3认同)
  • 您还可以输入 `df.drop(columns=['B', 'C'])` (2认同)

Ian*_*anS 131

有一种新的索引方法叫做difference.它返回原始列,并删除作为参数传递的列.

df2 = df[df.columns.difference(['B', 'D'])]
Run Code Online (Sandbox Code Playgroud)

在此,输出是用来滤除列BDdf.

  • `difference()`似乎也默认按字母顺序重新排序列 (8认同)
  • @slizb好点,基于[源代码](https://github.com/pandas-dev/pandas/blob/093aa8231eae92ff6cf7ef9564d62289b458aaff/pandas/core/common.py#L352)看起来实际上并不能保证返回索引的顺序,因为该方法使用集合. (4认同)
  • 似乎drop方法稍微快一些(~515μsvs~680μs),至少在15611行×5列数据帧的某些测试中,我希望在python 3.6和pandas 0.20.3中删除3列. (3认同)
  • 可以通过将“sort=False”传递给“difference()”来阻止排序。 (3认同)
  • 尼斯.与`df.drop(['B','D'],轴= 1)相比,这样做是否有利有弊? (2认同)
  • 对我来说,优点是代码可读性.我发现使用`drop`来选择反直觉的列. (2认同)

pig*_*box 66

你真的不需要将它转换为集合:

cols = [col for col in df.columns if col not in ['B', 'D']]
df2 = df[cols]
Run Code Online (Sandbox Code Playgroud)

  • 我计时了这个,差异和```[df.columns[~df.columns.isin['B','D']]```。这个答案是最快的。谢谢。 (4认同)

MrE*_*MrE 38

另一种选择,不在循环中删除或过滤:

import numpy as np
import pandas as pd

# Create a dataframe with columns A,B,C and D
df = pd.DataFrame(np.random.randn(100, 4), columns=list('ABCD'))

# include the columns you want
df[df.columns[df.columns.isin(['A', 'B'])]]

# or more simply include columns:
df[['A', 'B']]

# exclude columns you don't want
df[df.columns[~df.columns.isin(['C','D'])]]
Run Code Online (Sandbox Code Playgroud)

  • 应该是答案 (11认同)

小智 17

另请参阅内置DataFrame.filter功能.

简约但贪婪的方法(对于给定的df足够):

df.filter(regex="[^BD]")
Run Code Online (Sandbox Code Playgroud)

保守/懒惰的方法(仅限完全匹配):

df.filter(regex="^(?!(B|D)$).*$")
Run Code Online (Sandbox Code Playgroud)

保守和通用:

exclude_cols = ['B','C']
df.filter(regex="^(?!({0})$).*$".format('|'.join(exclude_cols)))
Run Code Online (Sandbox Code Playgroud)


Kap*_*aha 8

您有 4 列 A、B、C、D

这是选择新数据框所需列的更好方法:-

df2 = df1[['A','D']]
Run Code Online (Sandbox Code Playgroud)

如果您想改用列号,请使用:-

df2 = df1[[0,3]]
Run Code Online (Sandbox Code Playgroud)


tac*_*ell 6

你只需要转换set成一个list

import pandas as pd
df = pd.DataFrame(np.random.randn(100, 4), columns=list('ABCD'))
my_cols = set(df.columns)
my_cols.remove('B')
my_cols.remove('D')
my_cols = list(my_cols)
df2 = df[my_cols]
Run Code Online (Sandbox Code Playgroud)

  • 也许使用[drop](http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.drop.html?highlight=drop#pandas.DataFrame.drop)?`df.drop(my_cols,axis = 1)`将生成带有删除列的DataFrame视图.然后你只需要将它分配给新的DF:`df2 = df.drop(my_cols,axis = 1)` (3认同)

Lon*_*Rob 5

以下是创建排除列列表的副本的方法DataFrame

df = pd.DataFrame(np.random.randn(100, 4), columns=list('ABCD'))
df2 = df.drop(['B', 'D'], axis=1)
Run Code Online (Sandbox Code Playgroud)

不过要小心!您在问题中提到视图,这表明如果您进行了更改df,那么您也想df2进行更改。(就像数据库中的视图一样。)

此方法不能实现以下目的:

>>> df.loc[0, 'A'] = 999 # Change the first value in df
>>> df.head(1)
     A         B         C         D
0  999 -0.742688 -1.980673 -0.920133
>>> df2.head(1) # df2 is unchanged. It's not a view, it's a copy!
          A         C
0  0.251262 -1.980673
Run Code Online (Sandbox Code Playgroud)

还请注意,@ piggybox的方法也是如此。(尽管该方法很好用,而且很流畅,而且是Pythonic的。我并没有这么做!!)

有关视图与副本的更多信息,请参见此SO答案以及答案所指的Pandas文档的这一部分


pyl*_*ang 5

同样,在读取文件时,人们可能希望预先排除列,而不是浪费地将不需要的数据读入内存,然后再将其丢弃。

从 pandas 0.20.0 开始,usecols现在接受 callables1 此更新允许更灵活的选项来读取列:

skipcols = [...]
read_csv(..., usecols=lambda x: x not in skipcols)
Run Code Online (Sandbox Code Playgroud)

后一种模式本质上与传统usecols方法相反——仅跳过指定的列。


给定的

文件中的数据

import numpy as np
import pandas as pd


df = pd.DataFrame(np.random.randn(100, 4), columns=list('ABCD'))

filename = "foo.csv"
df.to_csv(filename)
Run Code Online (Sandbox Code Playgroud)

代码

skipcols = ["B", "D"]
df1 = pd.read_csv(filename, usecols=lambda x: x not in skipcols, index_col=0)
df1
Run Code Online (Sandbox Code Playgroud)

输出

          A         C
0  0.062350  0.076924
1 -0.016872  1.091446
2  0.213050  1.646109
3 -1.196928  1.153497
4 -0.628839 -0.856529
...
Run Code Online (Sandbox Code Playgroud)

细节

数据帧已写入文件。然后它作为一个单独的 DataFrame 被读回,现在跳过不需要的列(BD)。

请注意,对于 OP 的情况,由于数据已经创建,更好的方法是接受的答案,它从现有对象中删除不需要的列。然而,当直接从文件中读取数据到 DataFrame 中时,这里介绍的技术最有用。

这个问题中提出了一个“skipcols”选项的请求,并在以后的问题中得到解决