ChatGPT解决这个技术问题 Extra ChatGPT

在 Pandas 数据框中选择多列

如何从 df 中选择列 ab,并将它们保存到新的数据框 df1 中?

index  a   b   c
1      2   3   4
2      3   4   5

不成功的尝试:

df1 = df['a':'b']
df1 = df.ix[:, 'a':'b']
您永远不想使用 .ix,因为它不明确。如果必须,请使用 .iloc.loc
有没有一种方法可以在不参考标题名称的情况下完成?就像在 R 中一样,我可以这样做:> csvtable_imp_1 <- csvtable_imp[0:6] 并选择 0 到 6 之间的第一列的增量量。我所要做的就是读取用 readr lib 分隔的 csv 表。
我已经用它做了更多的工作。找到了可以按要求工作的东西。默认是选择字符数而不是列数。 infile_1 = largefile_stay.ix[:,0:6]
对于那些迟到的人,现在不推荐使用 ix。 Pandas 建议使用:loc(基于标签的索引)或 iloc(基于位置的索引)。

J
John Laudun

无法以您尝试的方式对列名(字符串)进行切片。

在这里,您有几个选择。如果您从上下文中知道要切出哪些变量,则可以通过将列表传递给 __getitem__ syntax([])来仅返回这些列的视图。

df1 = df[['a', 'b']]

或者,如果对它们进行数字索引而不是它们的名称很重要(例如,您的代码应该在不知道前两列的名称的情况下自动执行此操作),那么您可以这样做:

df1 = df.iloc[:, 0:2] # Remember that Python does not slice inclusive of the ending index.

此外,您应该熟悉 Pandas 对象的视图与该对象的副本的概念。上述方法中的第一个将在内存中返回所需子对象(所需切片)的新副本。

然而,有时 Pandas 中的索引约定不这样做,而是为您提供一个新变量,该变量仅引用与原始对象中的子对象或切片相同的内存块。第二种索引方式会发生这种情况,因此您可以使用 .copy() 方法对其进行修改以获取常规副本。发生这种情况时,更改您认为的切片对象有时会更改原始对象。随时注意这一点总是好的。

df1 = df.iloc[0, 0:2].copy() # To avoid the case where changing df1 also changes df

要使用 iloc,您需要知道列位置(或索引)。由于列位置可能发生变化,您可以使用 iloc 以及数据框对象的 columns 方法的 get_loc 函数来获取列索引,而不是硬编码索引。

{df.columns.get_loc(c): c for idx, c in enumerate(df.columns)}

现在您可以使用此字典通过名称和使用 iloc 访问列。


注意:df[['a','b']] 生成一个副本
是的,这在我的回答中是隐含的。如果您出于任何原因更喜欢使用 ix[],则有关副本的部分仅供参考。
ix 接受切片参数,因此您也可以获取列。例如,df.ix[0:2, 0:2] 获取左上角的 2x2 子数组,就像它为 NumPy 矩阵所做的一样(当然取决于您的列名)。您甚至可以对列的字符串名称使用切片语法,例如 df.ix[0, 'Col1':'Col5']。这将获取 df.columns 数组中恰好在 Col1Col5 之间排序的所有列。说 ix 索引行是不正确的。这只是它最基本的用途。它还支持比这更多的索引。因此,ix 完全适用于这个问题。
@AndrewCassidy 再也不要使用 .ix 了。如果要使用整数切片,请使用 .iloc ,它不包括最后一个位置,就像 Python 列表一样。
@dte324 如果您的 DataFrame 名为 df,则使用 df.iloc[:, [1, 4]]。通常,如果您想要这种类型的访问模式,您已经知道这些特定的列名,并且您可以使用 df.loc[:, ['name2', 'name5']],其中 'name2''name5' 是您想要的相应列的列字符串名称,或者查看例如 name2 = df.columns[1] 的名称。
q
questionto42standswithUkraine

从 0.11.0 版开始,列可以按照您尝试使用 .loc 索引器的方式进行切片:

df.loc[:, 'C':'E']

获得相同的列

df[['C', 'D', 'E']] # Mind, this makes a copy.

或者

df.loc[:, ['C', 'D', 'E']] # This does not make a copy (better).

并返回列 CE

随机生成的 DataFrame 的演示:

import pandas as pd
import numpy as np
np.random.seed(5)
df = pd.DataFrame(np.random.randint(100, size=(100, 6)),
                  columns=list('ABCDEF'),
                  index=['R{}'.format(i) for i in range(100)])
df.head()

Out:
     A   B   C   D   E   F
R0  99  78  61  16  73   8
R1  62  27  30  80   7  76
R2  15  53  80  27  44  77
R3  75  65  47  30  84  86
R4  18   9  41  62   1  82

要获取从 CE 的列(请注意,与整数切片不同,E 包含在列中):

df.loc[:, 'C':'E']

Out:
      C   D   E
R0   61  16  73
R1   30  80   7
R2   80  27  44
R3   47  30  84
R4   41  62   1
R5    5  58   0
...

基于标签选择行也是如此。从这些列中获取行 R6R10

df.loc['R6':'R10', 'C':'E']

Out:
      C   D   E
R6   51  27  31
R7   83  19  18
R8   11  67  65
R9   78  27  29
R10   7  16  94

.loc 还接受布尔数组,因此您可以选择数组中对应条目为 True 的列。例如,df.columns.isin(list('BCD')) 返回 array([False, True, True, True, False, False], dtype=bool) - 如果列名在列表 ['B', 'C', 'D'] 中,则返回 True;假的,否则。

df.loc[:, df.columns.isin(list('BCD'))]

Out:
      B   C   D
R0   78  61  16
R1   27  30  80
R2   53  80  27
R3   65  47  30
R4    9  41  62
R5   78   5  58
...

df.loc[:, 'C':'E'] 这是我正在寻找的确切答案。我将 C 和 E 放在另一个括号中,这是我的错误。谢谢
df.loc[] 似乎比 df[[]] 快。
@Sean.H 是的,the answer above 下高度赞成的评论应该足以证明。如果可以,请避免复制。 df.loc[] 更好。
P
Peter Mortensen

假设您的列名 (df.columns) 是 ['index','a','b','c'],那么您想要的数据位于第三列和第四列。如果您在脚本运行时不知道他们的名字,您可以这样做

newdf = df[df.columns[2:4]] # Remember, Python is zero-offset! The "third" entry is at slot two.

正如 EMS 在 his answer 中指出的那样,df.ix 对列进行更简洁的切片,但 .columns 切片接口可能更自然,因为它使用普通的一维 Python 列表索引/切片语法。

警告'index'DataFrame 列的错误名称。相同的标签也用于真正的 df.index 属性,即 Index 数组。因此,您的列由 df['index'] 返回,而真正的 DataFrame 索引由 df.index 返回。 Index 是一种特殊类型的 Series,针对其元素值的查找进行了优化。对于 df.index,它用于按标签查找行。该 df.columns 属性也是一个 pd.Index 数组,用于按标签查找列。


正如我在上面的评论中所指出的,.ix 仅用于行。用于通用切片,可用于多维切片。它基本上只是 NumPy 常用 __getitem__ 语法的一个接口。也就是说,只需应用转置操作 df.T,您就可以轻松地将列切片问题转换为行切片问题。您的示例使用 columns[1:3],这有点误导。 columns 的结果是 Series;注意不要把它当作一个数组来对待。此外,您可能应该将其更改为 columns[2:3] 以匹配您的“3rd & 4th”评论。
@Mr.F:我的 [2:4] 是正确的。您的 [2:3] 错误。并且使用标准 python 切片符号生成序列/系列不会误导 IMO。但我喜欢您绕过 DataFrame 接口以使用 ix 访问底层 numpy 数组。
在这种情况下你是正确的,但我想说的是,一般来说,slicing with labels in Pandas is inclusive of the slice endpoint(或者至少这是大多数以前的 Pandas 版本中的行为)。因此,如果您检索 df.columns 并希望 按标签 对其进行切片,那么您将拥有与 按整数索引位置 对其进行切片的不同切片语义。不过,我在之前的评论中肯定没有很好地解释它。
啊,现在我明白你的意思了。我忘记了 columns 是一个不可变的系列,并且 getter 已被覆盖以使用标签作为索引。感谢您花时间澄清。
请注意弃用警告:.ix 已弃用。因此这是有道理的:newdf = df[df.columns[2:4]]
P
Peter Mortensen

在最新版本的 Pandas 中,有一种简单的方法可以做到这一点。列名(它们是字符串)可以以您喜欢的任何方式进行切片。

columns = ['b', 'c']
df1 = pd.DataFrame(df, columns=columns)

这只能在创建时完成。问题是询问您是否已经在数据框中拥有它。
df1 = df.iloc[:, columns] 在您已经拥有数据框时有效。
而这个创建列名的创建界面一直都有。
@BálintSass 如果您已经知道列名而不仅仅是它们的整数位置(索引)。
W
Wes McKinney
In [39]: df
Out[39]: 
   index  a  b  c
0      1  2  3  4
1      2  3  4  5

In [40]: df1 = df[['b', 'c']]

In [41]: df1
Out[41]: 
   b  c
0  3  4
1  4  5

如果我想重命名列,例如:df[['b as foo', 'c as bar'],输出将列 b 重命名为 foo,列 c 重命名为 bar,该怎么办?
df[['b', 'c']].rename(columns = {'b' : 'foo', 'c' : 'bar'})
一个解释将是有序的。例如,要点是什么?您可以edit your answer - 无需“编辑:”、“更新:”或类似内容 - 答案应该看起来就像是今天写的一样。
P
Peter Mortensen

与熊猫,

机智的列名

dataframe[['column1','column2']]

通过 iloc 和具有索引号的特定列进行选择:

dataframe.iloc[:,[1,2]]

带有 loc 列名可以像这样使用

dataframe.loc[:,['column1','column2']]

P
Peter Mortensen

您可以使用 pandas.DataFrame.filter 方法过滤或重新排序列,如下所示:

df1 = df.filter(['a', 'b'])

这在链接方法时也非常有用。


filter 很棒,但并没有应有的知名度。特别是,您还可以使用这样的正则表达式:df.filter(regex='a|b')。我在回答这个问题时有一个更长的例子:stackoverflow.com/questions/29241836/…
过滤器还能够忽略“items= .. list”中不存在的列,这有时非常有用!
这是最好的答案
A
Alex Riley

您可以使用 Pandas DataFrame 上的 drop() 函数提供要删除的列列表并返回 DataFrame,其中仅包含所需的列。

只是说

colsToDrop = ['a']
df.drop(colsToDrop, axis=1)

将返回仅包含 bc 列的 DataFrame。

drop 方法记录在 here 中。


P
Peter Mortensen

我发现这个方法非常有用:

# iloc[row slicing, column slicing]
surveys_df.iloc [0:3, 1:4]

更多详细信息,请参见here


比如说,你会如何只考虑第 2 列和第 5 列?
那将是 surveys_df.iloc [:, [2,5]]
P
Peter Mortensen

从 0.21.0 开始,不推荐将 .loc[] 与一个或多个缺少标签的列表一起使用,而改用 .reindex。所以,你的问题的答案是:

df1 = df.reindex(columns=['b','c'])

在以前的版本中,只要找到至少一个键,使用 .loc[list-of-labels] 就可以工作(否则会引发 KeyError)。此行为已弃用,现在显示警告消息。推荐的替代方法是使用 .reindex()

Indexing and Selecting Data 阅读更多信息。


P
Peter Mortensen

你可以使用熊猫。

我创建数据框:

import pandas as pd
df = pd.DataFrame([[1, 2,5], [5,4, 5], [7,7, 8], [7,6,9]],
                  index=['Jane', 'Peter','Alex','Ann'],
                  columns=['Test_1', 'Test_2', 'Test_3'])

数据框:

       Test_1  Test_2  Test_3
Jane        1       2       5
Peter       5       4       5
Alex        7       7       8
Ann         7       6       9

按名称选择一列或多列:

df[['Test_1', 'Test_3']]

       Test_1  Test_3
Jane        1       5
Peter       5       5
Alex        7       8
Ann         7       9

您还可以使用:

df.Test_2

你得到列 Test_2

Jane     2
Peter    4
Alex     7
Ann      6

您还可以使用 .loc() 从这些行中选择列和行。这称为“切片”。请注意,我从列 Test_1Test_3

df.loc[:, 'Test_1':'Test_3']

“切片”是:

       Test_1  Test_2  Test_3
Jane        1       2       5
Peter       5       4       5
Alex        7       7       8
Ann         7       6       9

如果您只需要列 Test_1Test_3 中的 PeterAnn

df.loc[['Peter', 'Ann'], ['Test_1', 'Test_3']]

你得到:

       Test_1  Test_3
Peter       5       5
Ann         7       9

P
Peter Mortensen

如果你想通过行索引和列名获取一个元素,你可以像 df['b'][0] 那样做。它和你想象的一样简单。

或者您可以使用 df.ix[0,'b'] - 混合使用索引和标签。

注意: 自 v0.20 起,ix 已被弃用,取而代之的是 loc / iloc


P
Peter Mortensen
df[['a', 'b']]  # Select all rows of 'a' and 'b'column 
df.loc[0:10, ['a', 'b']]  # Index 0 to 10 select column 'a' and 'b'
df.loc[0:10, 'a':'b']  # Index 0 to 10 select column 'a' to 'b'
df.iloc[0:10, 3:5]  # Index 0 to 10 and column 3 to 5
df.iloc[3, 3:5]  # Index 3 of column 3 to 5

第三行应该有 df.loc[0:10, 'a':'b']。我刚刚编辑了它。
P
Peter Mortensen

尝试使用 pandas.DataFrame.get(参见 the documentation):

import pandas as pd
import numpy as np

dates = pd.date_range('20200102', periods=6)
df = pd.DataFrame(np.random.randn(6, 4), index=dates, columns=list('ABCD'))
df.get(['A', 'C'])

P
Peter Mortensen

一种不同且简单的方法:迭代行

使用 itrows

 df1 = pd.DataFrame() # Creating an empty dataframe
 for index,i in df.iterrows():
    df1.loc[index, 'A'] = df.loc[index, 'A']
    df1.loc[index, 'B'] = df.loc[index, 'B']
    df1.head()

Please do not recommend the use of iterrows(). 它公然促成了 pandas 历史上最糟糕的反模式。
您能否解释一下“最糟糕的反模式”是什么意思?
恕我直言, iterrows() 应该是使用熊猫时的最后一个选项。
@Ankita 从所有 StackOverflow 的 most copy-paste answer 中检查 cs95 的 2nd answerHow to iterate over rows in a DataFrame in Pandas
P
Peter Mortensen

前面的答案中讨论的不同方法是基于这样的假设,即用户知道要删除或子集的列索引,或者用户希望使用一系列列(例如在 'C' : 'E' )。

pandas.DataFrame.drop() 当然是根据用户定义的列列表对数据进行子集化的一个选项(尽管您必须小心,始终使用数据帧的副本,并且不应将就地参数设置为 True !!)

另一种选择是使用 pandas.columns.difference(),它对列名进行设置差异,并返回包含所需列的数组索引类型。以下是解决方案:

df = pd.DataFrame([[2,3,4], [3,4,5]], columns=['a','b','c'], index=[1,2])
columns_for_differencing = ['a']
df1 = df.copy()[df.columns.difference(columns_for_differencing)]
print(df1)

输出将是:

    b   c
1   3   4
2   4   5

copy() 不是必需的。即:df1 = df[df.columns.difference(columns_for_differencing)] 将返回一个新的/复制的数据帧。您将能够在不更改 df 的情况下修改 df1。谢谢你,顺便说一句。这正是我所需要的。
P
Peter Mortensen

您还可以使用 df.pop()

>>> df = pd.DataFrame([('falcon', 'bird',    389.0),
...                    ('parrot', 'bird',     24.0),
...                    ('lion',   'mammal',   80.5),
...                    ('monkey', 'mammal', np.nan)],
...                   columns=('name', 'class', 'max_speed'))
>>> df
     name   class  max_speed
0  falcon    bird      389.0
1  parrot    bird       24.0
2    lion  mammal       80.5
3  monkey  mammal

>>> df.pop('class')
0      bird
1      bird
2    mammal
3    mammal
Name: class, dtype: object

>>> df
     name  max_speed
0  falcon      389.0
1  parrot       24.0
2    lion       80.5
3  monkey        NaN

请使用df.pop(c)


P
Peter Mortensen

我已经看到了几个答案,但我仍然不清楚。您将如何选择那些感兴趣的列?

答案是,如果您将它们收集在一个列表中,您可以使用该列表引用这些列。

例子

print(extracted_features.shape)
print(extracted_features)

(63,)
['f000004' 'f000005' 'f000006' 'f000014' 'f000039' 'f000040' 'f000043'
 'f000047' 'f000048' 'f000049' 'f000050' 'f000051' 'f000052' 'f000053'
 'f000054' 'f000055' 'f000056' 'f000057' 'f000058' 'f000059' 'f000060'
 'f000061' 'f000062' 'f000063' 'f000064' 'f000065' 'f000066' 'f000067'
 'f000068' 'f000069' 'f000070' 'f000071' 'f000072' 'f000073' 'f000074'
 'f000075' 'f000076' 'f000077' 'f000078' 'f000079' 'f000080' 'f000081'
 'f000082' 'f000083' 'f000084' 'f000085' 'f000086' 'f000087' 'f000088'
 'f000089' 'f000090' 'f000091' 'f000092' 'f000093' 'f000094' 'f000095'
 'f000096' 'f000097' 'f000098' 'f000099' 'f000100' 'f000101' 'f000103']

我有以下列表/NumPy 数组 extracted_features,指定 63 列。原始数据集有 103 列,我想准确提取那些,然后我会使用

dataset[extracted_features]

你最终会得到这个

https://i.stack.imgur.com/3jLjo.png

这是您在 machine learning 中经常使用的东西(更具体地说,在特征选择中)。我也想讨论其他方式,但我认为其他 Stack Overflower 用户已经涵盖了这一点。


f
fcdt

要选择多个列,然后提取并查看它们:df 以前命名为数据框,然后创建新的数据框 df1,然后选择要提取和查看的列 A 到 D。

df1 = pd.DataFrame(data_frame, columns=['Column A', 'Column B', 'Column C', 'Column D'])
df1

所有必需的列都会显示出来!


M
Mykola Zotko

要排除某些列,您可以在列索引中drop它们。例如:

   A   B    C     D
0  1  10  100  1000
1  2  20  200  2000

选择除两个之外的所有:

df[df.columns.drop(['B', 'D'])]

输出:

   A    C
0  1  100
1  2  200

您还可以使用方法 truncate 选择中间列:

df.truncate(before='B', after='C', axis=1)

输出:

    B    C
0  10  100
1  20  200

S
Suleyman Suleymanzade
def get_slize(dataframe, start_row, end_row, start_col, end_col):
    assert len(dataframe) > end_row and start_row >= 0
    assert len(dataframe.columns) > end_col and start_col >= 0
    list_of_indexes = list(dataframe.columns)[start_col:end_col]
    ans = dataframe.iloc[start_row:end_row][list_of_indexes]
    return ans

只需使用此功能


对我不起作用:TypeError: '>' 在 'int' 和 'str' 的实例之间不支持
N
Nayem Jaman Tusher

我认为这是实现目标的最简单方法。

将熊猫导入为 pd cols = ['a', 'b'] df1 = pd.DataFrame(df, columns=cols) df1 = df.iloc[:, 0:2]