【问题标题】:Why does a column from pandas DataFrame not work in this loop?为什么 pandas DataFrame 中的列在此循环中不起作用?
【发布时间】:2016-12-04 14:26:14
【问题描述】:

我有一个从篮球参考中获取的带有球员姓名的 DataFrame。下面的代码是我构建 DataFrame 的方式。它有 5 列球员姓名,但每个姓名也有球员的位置。

url = "http://www.basketball-reference.com/awards/all_league.html"
dframe_list = pd.io.html.read_html(url)
df = dframe_list[0]
df.drop(df.columns[[0,1,2]], inplace=True, axis=1)
column_names = ['name1', 'name2', 'name3', 'name4', 'name5']
df.columns = column_names
df = df[df.name1.notnull()]

我正在尝试拆分职位。为此,我计划为每个名称列制作一个 DataFrame:

name1 = pd.DataFrame(df.name1.str.split().tolist()).ix[:,0:1]
name1[0] = name1[0] + " " + name1[1]
name1.drop(name1.columns[[1]], inplace=True, axis=1)

因为我有五列,所以我想我会用一个循环来做这个

column_names = ['name1', 'name2', 'name3', 'name4', 'name5']
for column in column_names:
    column = pd.DataFrame(df.column.str.split().tolist()).ix[:,0:1]
    column[0] = column[0] + " " + column[1]
    column.drop(column.columns[[1]], inplace=True, axis=1)
    column.columns = column

然后我会将所有这些 DataFrame 重新组合在一起。

df_NBA = [name1, name2, name3, name4, name5]
df_NBA = pd.concat(df_NBA, axis=1)

我是 python 新手,所以我确信我正在以一种非常麻烦的方式执行此操作,并且希望获得有关如何更快地执行此操作的建议。但我的主要问题是,当我在单个列上运行代码时它工作正常,但如果我运行循环时出现错误:

AttributeError: 'DataFrame' object has no attribute 'column'

似乎循环df.column.str 的部分引起了一些问题?我摆弄了列表,用括号列(我仍然不明白为什么有时我将 DataFrame 列括起来,有时它是 .column,但这是一个更大的问题)和其他随机的东西。

当我尝试@BrenBarn 的建议时

df.apply(lambda c: c.str[:-2])

Jupyter notebook 中弹出以下内容:

SettingWithCopyWarning: 
A value is trying to be set on a copy of a slice from a DataFrame

See the caveats in the documentation:    http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy
  if __name__ == '__main__':

查看 DataFrame,实际上没有任何变化,如果我正确理解文档,此方法会创建带有编辑的 DataFrame 的副本,但这是一个临时副本,之后会被丢弃,因此实际的 DataFrame 不会改变。

【问题讨论】:

  • 你是说df[column]也行不通吗?
  • df.column 对应于df['column'],而不是df[column]。所以当 column 是一个变量时,你不能这样使用它。
  • @BrenBarn,是的,如果我使用df[column]df['column'],它不起作用,我想这就是@ayhan 的意思。那么有答案了吗?
  • 我无法重现您的问题。如果我使用df[column] 运行您的代码,我会收到错误,但它们与重置列名(您的column.columns = column)有关。此外,您的数据样本只有两列,但您的代码仍尝试迭代超过 5 列,从而导致更多错误。
  • 编辑了问题以反映我正在使用的实际 DataFrame。感谢@BrenBarn 的建议。

标签: python pandas for-loop dataframe


【解决方案1】:

如果位置标签总是只有一个字符,简单的解决方案是这样的:

>>> df.apply(lambda c: c.str[:-2])
           name1         name2
0     Marc Gasol  Lebron James
1      Pau Gasol  Kevin Durant
2  Dwight Howard  Kyrie Irving

Series 的 str 属性允许您执行字符串操作,包括索引,因此这只是修剪每个值的最后两个字符。

至于你关于df.column的问题,这个问题比pandas更笼统。这两件事不一样:

# works
obj.attr

# doesn't work
attrName = 'attr'
obj.attrName

当您想要访问名称存储在变量中的属性时,不能使用点表示法。通常,您可以改用getattr 函数。但是,pandas 通过将名称指定为 string(而不是源代码标识符)来提供括号表示法来访问列。所以这两个是等价的:

df.some_column

columnName = "some_column"
df[columnName]

在您的示例中,将对 df.column 的引用更改为 df[column] 应该可以解决该问题。但是,正如我在评论中提到的,您的代码也存在其他问题。就解决手头的任务而言,我在答案开头展示的字符串索引方法要简单得多。

【讨论】:

  • 感谢您的解决方案,不幸的是,当我在实际的 DataFrame 上尝试此操作时,它实际上并没有改变任何东西。在 Jupyter 笔记本中会出现一个红色框,并指出“试图在来自 DataFrame 的切片的副本上设置一个值”,并表示这会引发 SettingWithCopy 错误。文档指出,此方法可能会返回 DataFrame 临时视图的副本,该副本随后被丢弃,因此不会运行。
  • @vino88:然后请编辑您的问题以包含一个独立的示例来演示该问题。 (或者问一个单独的问题,如果你的新问题真的是关于这种新的方法并且与你在这里发布的代码无关。)
猜你喜欢
  • 2023-01-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-01-08
  • 1970-01-01
  • 1970-01-01
  • 2019-11-14
  • 2015-01-28
相关资源
最近更新 更多