【问题标题】:Why can't a DataFrame Index be used for data dictionary lookup in .apply()?为什么 DataFrame 索引不能用于 .apply() 中的数据字典查找?
【发布时间】:2020-03-27 20:08:09
【问题描述】:

我有一个 DataFrame 和一个字典。我想根据 Dictionary 为 DataFrame 中的新列赋值。

ContinentDictionary  = {'United States':'North America', 
                        'Japan':'Asia', 
                        'United Kingdom':'Europe', 
                        'Australia':'Australia', 
                        'Argentina':'South America'}

c1 = pd.Series({'Size':'Large','Pi':6,'Pr':160})
c2 = pd.Series({'Size':'Small','Pi':9,'Pr':235})
c3 = pd.Series({'Size':'Large','Pi':12,'Pr':300})
Countries = pd.DataFrame([c1,c2,c3],index=['United States','Japan','United Kingdom'])
Countries.index.name='Country'

这完成了工作,为国家数据框中的每个国家/地区分配了一个大陆:

Countries['Continent'] = Countries.index.map(lambda x: ContinentDictionary[x])

这也有效,但我需要事先将索引“国家”设置为一列以使 .apply 工作:

Countries['Continent'] = Countries.reset_index(inplace = True)
Countries['Continent'] = Countries.apply(lambda x: ContinentDictionary[x['Country']], axis=1)

我想更好地理解为什么这两种方法不起作用,并希望得到解释:

  1. Countries['Continent'] = Countries.apply(lambda x: ContinentDictionary[x.index], axis=1)
  2. Countries['Continent'] = ContinentDictionary[Countries.index]

两者都给出:

TypeError: ("unhashable type: 'Index'"

在这两者中,我可以想象为什么 #2 可能不起作用,但仍然希望更好地理解。

【问题讨论】:

  • 变量名称应遵循lower_case_with_underscores 样式。另外,请问您为什么将国家名称设置为索引,而不是简单地将其作为列?
  • 谢谢,我会注意正确的约定!作为索引的国家名称是我被赋予使用的数据集。我确实将其更改为一列,并且能够使 .apply() 像上面一样工作。但我仍然不明白为什么我可以通过索引(上面的#1)。
  • apply()方法可以简化为countries_df['country_name'].map(continent_dict)

标签: python pandas dataframe data-science


【解决方案1】:

这取决于 pandas 的版本,在旧版本中需要添加 .get,解决方案也简化为删除 lambda 并仅通过 dictionary

Countries['Continent'] = Countries.index.map(ContinentDictionary.get)
print (Countries)
                 Size  Pi   Pr      Continent
United States   Large   6  160  North America
Japan           Small   9  235           Asia
United Kingdom  Large  12  300         Europe

编辑:从版本pandas 0.23+ 可以使用字典或系列作为映射器:

Index.map() 现在可以接受系列和字典输入对象(GH12756、GH18482、GH18509)。

【讨论】:

  • 谢谢,是的,我正在使用该解决方案。此外,我在第一次尝试中使用了 .get ,但这也不起作用。我不明白为什么可以传递单元格值时不能传递索引。
  • 很好,我不敢相信我忘记了 Index.map() 是一件事。 @jammer_man
  • @AlexanderCécile 谢谢,我在发布之前得到了那个解决方案。但我想了解为什么在 apply 函数中传递索引不起作用。我只是对我肤浅的理解不满意。
  • @jammer_man 和apply()没有关系,是不能作为字典的key。即使可以,我认为代码没有多大意义:您将整个索引作为键传递!考虑时将 Index 类型替换为 List,这样会更简单一些。
  • @jammer_man 不敢相信我忘了回答这个问题。您可以将索引转换为字符串,这就是我在回答中显示的内容。不幸的是,您是对的,是的,您不能将其用作字典的键。
【解决方案2】:

这是对您的一些 cmets 的回应。


你写的 我认为 axis=1 不会让我将整个索引作为键传递,而是一个索引?我不完全确定我理解你的意思,所以让我尝试澄清一些事情。

使用axis=1,该函数对行进行操作。每行都转换为一个系列。以下是其中一行看起来像系列的示例:

Size    Large
Pi          6
Pr        160
Name: United States, dtype: object

当您调用x.index 时,您希望在DataFrame 中收到行x 的索引。其实你得到系列的索引x

Index(['Size', 'Pi', 'Pr'], dtype='object')

所以你是说,我只能使用“索引”值作为字典的键,而没有办法将索引转换为字符串?索引对象不能用作字典中的键,或在任何需要可散列对象的情况下。您可以将它们转换为字符串,就像我在上面所做的那样。


正如@Jezrael 在 cmets 中提到的,在 Series 上调用 .apply() 可以获得单个元素,在这种情况下它们没有索引。

【讨论】:

  • 啊,我想我明白了,我觉得自己像个白痴。我一直认为axis = 1返回一行(不一定是系列),我可以访问每个元素。我将该行想象成如下所示:Index: 'Japan' . Size: 'Small' 。 Pi: 9 . Pr:300。通过以下方式访问我认为的“索引”感觉很方便:row.index
  • 这与能够通过以下方式获取和使用行的索引形成对比:for index, row in Countries.iterrows(): print(index)
  • @jammer_man DataFrame 行的索引,是的。该行在.apply() 中有自己的索引。
猜你喜欢
  • 1970-01-01
  • 2023-02-01
  • 1970-01-01
  • 1970-01-01
  • 2022-10-26
  • 2015-10-31
  • 2021-02-27
  • 1970-01-01
  • 2011-03-19
相关资源
最近更新 更多