Python 对于数据帧中一行中的每个列表,对列表中所有可能的值对执行操作

Python 对于数据帧中一行中的每个列表,对列表中所有可能的值对执行操作,python,pandas,dataframe,nested,itertools,Python,Pandas,Dataframe,Nested,Itertools,我认识到这种嵌套方法并不是pandas的设计初衷,可能也没有任何特别快速的解决方案,但我非常感谢您的帮助 我有一个数据框,其中一列包含整数列表。我希望,对于每一行,在该列表中查找每一对(不相同,例如非(1,1))整数,并对其执行操作。这些列表的长度不一定相同 额外的细节是每行包含一个3D顶点,这些整数是另一个3D顶点的ID,存储在单独的数据框中。对于每一行,我想找到所有可能的点击对之间的角度,以该行的顶点为原点,然后求平均值,然后做一些其他的事情得到“beta”。数学上非常简单,但是我必须运行这

我认识到这种嵌套方法并不是pandas的设计初衷,可能也没有任何特别快速的解决方案,但我非常感谢您的帮助

我有一个数据框,其中一列包含整数列表。我希望,对于每一行,在该列表中查找每一对(不相同,例如非
(1,1)
)整数,并对其执行操作。这些列表的长度不一定相同

额外的细节是每行包含一个3D顶点,这些整数是另一个3D顶点的ID,存储在单独的数据框中。对于每一行,我想找到所有可能的点击对之间的角度,以该行的顶点为原点,然后求平均值,然后做一些其他的事情得到“beta”。数学上非常简单,但是我必须运行这个程序的行数非常大,所以我希望尽可能地加快它的速度

我试过两种方法

方法1-应用()

我采用的第一种(非矢量化)方法是使用一个单独的函数,该函数获取行,生成一个新的2列数据帧,其中包含使用
itertools.combinations
生成的整数对。然后使用连接获取顶点信息并执行操作。然后我只使用
pd.DataFrame.apply()

以下是没有实际计算的简化代码:

# Geometry df, map of id (cable) to vertex
geo = geo[["cable","x","y","z"]

def _beta_single(row):
    # "cable" is the ID (integer) 
    cables = event["cable"]
    pairs = [combo for combo in combinations(cables,2)]
    pairs = pd.DataFrame(pairs, columns=["cable_1","cable_2"])

    # Rename geo to have suffixes of vertex after merge
    geo.columns = geo.columns.map(lambda x: str(x) + "_1")
    # Get both hit locations
    pairs = pairs.merge(geo, on="cable_1")
    # Get rid of _1 suffix, add _2
    geo.columns = geo.columns.map(lambda x: str(x)[:-2] + "_2")
    pairs = pairs.merge(geo, on="cable_2")
  
    # Perform calculations to get "beta" value (float)
     row["beta"] = dostuff(pairs)

df = df.apply(_beta_single, axis=1)
这很慢。可能有一些优化可能会有所帮助,但对于>100k行、200C2对,似乎需要几个小时的处理时间

方法2-大量列

第二种方法是在df中为列表中的每个整数创建一个新列,如下所示:

nhits = df["cable"].str.len()

hit_cols = ["cable_%i" % (x+1) for x in range(max_nhits)]

# Convert cable column to list of lists
cable_lists = df["cable"].tolist()
# Make df of hits
df[hit_cols] = pd.DataFrame(cable_lists, index=df.index)
然后,我再次使用
itertools.combinations
查找所有可能的组合,但这次是所有可能的列对,如:

col\u pairs=[组合中组合的组合(范围(1,(最大值+1)),2)]

然后循环这些,将对中的列与顶点贴图合并,以获得两个顶点:

for col_pair in col_pairs:
    # Column suffix
    s1 = "_%i" % col_pair[0]
    s2 = "_%i" % col_pair[1]

    cables_1 = df["cable" + s1]
    cables_2 = df["cable" + s2]

    geo_1 = pd.merge(cables_1, geo, left_on=("cable" + s1), right_on="cable")
    geo_2 = pd.merge(cables_2, geo, left_on=("cable" + s2), right_on="cable")

    beta = dostuff_vector(geo_1, geo_2)
对于伪代码很抱歉,但是数学在这里并不重要,所以如果我省略它,会更清楚

这种方法肯定比另一种方法快,但对于方法1中提到的相同大小的df,仍然需要半小时


对不起,我的帖子太长了,我只是想展示一下我已经玩过的东西。我想我要找的是一个很好的矢量化itertools风格的东西。我曾考虑过创建一列
itertools.compositions
对象,但嵌套迭代遇到了麻烦。有人建议我以某种形式使用类似于
groupby
的东西可能是最好的,但我不确定在这种情况下会是什么样子。

这些数据帧是代表图形的吗?如果是这样,您是否考虑将其导入NetworkX?不是图形,不是。每一行都是一个发光事件,具有一个发射顶点和多个灯光可能照射的点(ID对应于这些点)。是否可以为
geo
事件添加一些带有一组小型一致示例记录的代码,例如,每项记录5条左右?第一种方法可以在不使用数据帧操作的情况下大大加快速度。将其保存在迭代器中可能会更有效。你想要的就是最后的测试版,对吗?