对列表中所有可能的值对执行操作,对 Pandas DataFrame 中一行中的每个列表

问题描述

我认识到这种嵌套方法并不是 Pandas 的真正工作方式,并且可能没有任何特别快速解决方案,但我很感激任何帮助。

我有一个 Pandas DataFrame,其中一列包含整数列表。我想,对于每一行,找到此列表中的每一对(不相同,例如不是 (1,1))整数,并对其执行操作。这些列表的长度不一定相同。

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

我尝试了两种方法

方法 1 - apply()

我采用的第一个(非矢量化)方法是使用一个单独的函数获取行,为使用 itertools.combinations 生成的整数对创建一个新的 2 列 DataFrame。然后我使用连接来获取顶点信息并执行我的操作。然后我只使用 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_pairs = [combo for combo in combinations(range(1,(max_nhits+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,left_on=("cable" + s2),right_on="cable")

    beta = dostuff_vector(geo_1,geo_2)

抱歉我写了伪代码,但数学在这里并不重要,所以如果我省略它会更清楚。

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

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

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...