【问题标题】:Replacing Names with Index From Separate File using Pandas使用 Pandas 将名称替换为来自单独文件的索引
【发布时间】:2013-04-13 01:42:45
【问题描述】:

我有一个节点和一个边列表,如下所示:

Id   Label   Type
1   fie      gnome
2   fou      giant
3   fim      gnome
4   fee      dwarf

Source   target  Weight
fie   fou   2
fie   fim   2
fou   fee   2
fee   fim   3

如何将源文件和目标文件中的名称替换为节点文件中的索引?

最终的输出应该是:

Source target   Weight
1      2        2
1      3        2
2      4        2
4      3        3

【问题讨论】:

  • 我不确定您希望输出的样子。你想让第二个文件的第一行变成gnome giant 2吗?
  • 谢谢--编辑添加所需的输出。

标签: python indexing pandas


【解决方案1】:

我可能会从nodes.Labelnodes.Id 构建一个dict,然后将其传递给replace()applymap。例如:

>>> weight.stack().replace(dict(zip(nodes.Label, nodes.Id))).unstack()
  Source target Weight
0      1      2      2
1      1      3      2
2      2      4      2
3      4      3      3
>>> d = dict(zip(nodes.Label, nodes.Id))
>>> weight.applymap(lambda x: d.get(x,x))
   Source  target  Weight
0       1       2       2
1       1       3       2
2       2       4       2
3       4       3       3

一些解释。首先,我们从 DataFrames 开始:

>>> nodes
   Id Label   Type
0   1   fie  gnome
1   2   fou  giant
2   3   fim  gnome
3   4   fee  dwarf
>>> weight
  Source target  Weight
0    fie    fou       2
1    fie    fim       2
2    fou    fee       2
3    fee    fim       3

然后我们将 dict 替换为:

>>> d = dict(zip(nodes.Label, nodes.Id))
>>> d
{'fou': 2, 'fim': 3, 'fee': 4, 'fie': 1}

不幸的是,.replace() 不像您认为的那样在 DataFrame 上工作,因为它适用于行和列,而不是元素。但是我们可以stackunstack 来解决这个问题:

>>> weight.stack()
0  Source    fie
   target    fou
   Weight      2
1  Source    fie
   target    fim
   Weight      2
2  Source    fou
   target    fee
   Weight      2
3  Source    fee
   target    fim
   Weight      3
dtype: object
>>> weight.stack().replace(d)
0  Source    1
   target    2
   Weight    2
1  Source    1
   target    3
   Weight    2
2  Source    2
   target    4
   Weight    2
3  Source    4
   target    3
   Weight    3
dtype: object
>>> weight.stack().replace(d).unstack()
  Source target Weight
0      1      2      2
1      1      3      2
2      2      4      2
3      4      3      3

或者,我们也可以只使用lambdaapplymap。字典有一个get 方法,它接受一个默认参数,所以somedict.get(k, 'default value goes here') 将向上查找键k,如果找到该键则返回相应的值,否则返回第二个参数。所以d.get(x, x) 要么将x 更改为字典中的相应值,要么返回x 并不管它。因此:

>>> weight.applymap(lambda x: d.get(x,x))
   Source  target  Weight
0       1       2       2
1       1       3       2
2       2       4       2
3       4       3       3

PS:如果您只想将替换应用到某些列,则基于 dict 的相同方法将起作用,但您必须限制应用程序。例如,如果您想换一种方式,您可能不希望权重列中的2 变为fou

【讨论】:

  • 有趣!似乎堆叠/取消堆叠会有点贵。第二种方式更快吗?
  • 堆叠和取消堆叠并没有你想象的那么慢,但至少在这种情况下它更慢。在我的测试中,applymap 方法似乎总是快 2 倍左右,但是 YMMV,如果这是一个瓶颈,我会非常惊讶。
  • 奇怪的是,两者都不起作用。 replace 方法只替换了第一列。
  • 我觉得这很令人惊讶。您能否找到一个不起作用的最小示例并发布.to_dict()?一种可能性是一列中的空格在另一列中不存在,因此替换不起作用,因为实际上没有匹配项。
  • 嗯......空白是可能的......让我试试。
猜你喜欢
  • 2021-06-29
  • 1970-01-01
  • 2020-08-23
  • 1970-01-01
  • 2014-12-11
  • 2017-10-29
  • 2014-08-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多