【发布时间】:2014-11-13 11:57:22
【问题描述】:
我正在使用 Python、Pandas 和 Numpy,尽管这个问题感觉像是一个更通用的算法设计问题。
我有一个元素列表(实际上是一个数组),我想生成该列表的排列。但是,某些项目不允许位于列表中的某些位置。我想生成一个遵守这些限制的排列。有什么有效的方法来做到这一点?
我的实际用例是一个 Pandas 数据框,有两列 X 和 Y。 X 和 Y 都具有相同的编号,但顺序不同。数字不是唯一的。同一行的X 和Y 中没有数字出现(即没有数字与自身匹配)。我想置换Y,同时保持没有数字与自身匹配的限制。我一直在 Y 上调用 Numpy 的 permute,但大约 1% 的结果行有 X==Y。
用例子编辑:
import pandas as pd
import numpy as np
data = [[1,2],
[1,4],
[4,2],
[2,3]]
df = pd.DataFrame(columns=['X', 'Y'],
data=data)
df_permuted = df.copy()
df_permuted.Y = np.random.permutation(df.Y)
print(df.X==df.Y)
#0 False
#1 False
#2 False
#3 False
#dtype: bool
print(df_permuted.X==df_permuted.Y)
#0 False
#1 False
#2 False
#3 True
#dtype: bool
编辑: 明显的算法太慢/无法扩展,是这样的:
for every row i:
define the set of valid candidate "other" rows (where i.X != other.Y and i.Y != other.X)
grab a row from the valid set
swap i.Y and other.Y
在我们的 Pandas 示例中,这将是:
from numpy.random import choice
for i in df.index:
other_rows = df[(df.ix[i].X != df.Y) * (df.ix[i].Y != df.X)]
selected_row = choice(other_rows.index)
original_Y = df.ix[i].Y
df.ix[i].Y = df.ix[selected_row].Y
df.ix[selected_row].Y = original_Y
print(df.X==df.Y)
#0 False
#1 False
#2 False
#3 False
#dtype: bool
问题是这太慢了,而且根本没有并行化。有没有办法并行化它?我想答案是“否”,因为在一行上进行的交换会影响下一行的有效“其他”。
编辑规模感:
大约 1.4*10^7 行,X 中有 2*10^6 个唯一值,Y 中有类似的数字。并且需要生成大约 10^3 个独立排列。我实际上采用多组行并独立排列它们的内容,有些组非常小(例如 10 行),但许多组相当大(10 ^ 5)。这买了一点帮助,但最后还是有很多行!只需在 10^7 行上运行一个简单的 np.random.permutation 大约需要 7 秒,这已经足够了。运行上面的受限置换算法(在 numpy 而不是 pandas 中实现以提高速度)只需 10^3 行就需要 7 秒。哎呀!
【问题讨论】:
-
你能举个例子吗?
-
使用
permutation函数后过滤掉这些值是否足够? -
如何过滤?可能是排列过程匹配,例如所有的 2 给对方。然后只抓取那些 X==Y 的值并排列它们不会解决任何问题;得到的排列与之前的 2 相同。
-
您说“X 和 Y 都具有相同的数字,但顺序不同”,但在您的示例中,Y 不包含 1,X 不包含 3,所以我不确定您是什么意思是。我认为您遇到的问题是:X 和 Y 是任意多重集,并且您想提出对,使得一侧的所有值构成 X,另一方面构成 Y,并且没有值与自身配对。对吗?
-
并且要明确一点 - 你想要任何这样的配对,你并不是想公平地选择一个或任何东西。
标签: python algorithm numpy pandas permutation