Python 应用于数据帧的*交错*组

Python 应用于数据帧的*交错*组,python,pandas,numpy,dataframe,scipy,Python,Pandas,Numpy,Dataframe,Scipy,我有一个3轴数据的DataFrames,带有一个成员标签,用于分组: df = pd.DataFrame( [[0, 1, 2, 0], [-1, 0, 1, 0], [-2, 0, 3, 1], [1, 1, 3, 1], [1, 0, 2, 2], [1, 0, 3, 2],

我有一个3轴数据的DataFrames,带有一个成员标签,用于分组:

df = pd.DataFrame( [[0, 1, 2,  0], 
                    [-1, 0, 1, 0],
                    [-2, 0, 3, 1],
                    [1, 1, 3,  1],
                    [1, 0, 2,  2],
                    [1, 0, 3,  2],
                    [6, 2, 1,  5],
                    [-4, 3, 0, 5],
                    [1, 0, -1, 6],
                    [0, 0, 3,  6]], columns = ['x', 'y', 'z', 'member'])
我的目标有点矫揉造作:我希望找到每个组的点与下一个
n\u skip
组之间的成对距离,从最小到最大排序。这个
n_skip
就是我所说的交错:

例如,对于
n_skip=2
,我希望找到以下距离:

  • member==0的行与
    member==1、2的行相对
  • member==1的行与
    member==2,5的行相对
  • member==2的行与
    member==5、6的行相对
  • member==5的行与
    member==6的行相对
  • 不计算
    成员==6
有没有一种没有嵌套for循环的高性能方法?直观地说,我无法使用传统的
apply
来并行化数据帧上的函数。将函数应用于交错组的快速方法是什么


EDIT1 我的解决方案(仅适用于一个轴):

    ## Heading ### Organize by group membership
    groups = df.groupby('member')

    # Define constants
    max_member = 6
    n_skip = 2
    start_row = 0
    matrix = np.zeros((df.shape[0], df.shape[0]))

    # Iterate for each group
    for i in range(max_member):

        try:
            pts_curr = groups.get_group(i)

        except KeyError:
            continue

        # Save end row index 
        end_row = start_row + pts_curr.shape[0]    

        # Save start col index
        start_col = end_row
        
        # Grab the destination group nodes
        for j in range(i+1, int(np.min([i+n_skip+1, max_member]))):

            try:
                pts_clr_next = groups.get_group(j)

            except KeyError:
                continue

            # Save end col index
            end_col = start_col + pts_clr_next.shape[0]

            # Calculate cdist
            z_sq = cdist(pts_curr[['z']], pts_next[['z']])

            # Save results in matrix at right positions
            matrix[start_row:end_row, start_col:end_col] = z_sq
            
            # update col index
            start_col = end_col

        # update row index
        start_row = end_row


对4K行进行交叉合并并不太糟糕(产生约1600万行)。让我们尝试交叉合并和查询:

n = 2
# dummy key
df['dummy'] = 1
# this is the member group number
df['rank'] = df['member'].rank(method='dense')

# cross merge and filter
new_df = (df.merge(df, on='dummy')
            .query('rank_x<rank_y<=rank_x+@n')
         )

# euclidean distance
dist = (new_df[['x_x','y_x','z_x']].sub(new_df[['x_y','y_y','z_y']].values)**2).sum(1)**.5

# output dataframe with member label
pd.DataFrame({'member1':new_df['member_x'], 'member2':new_df['member_y'],
              'dist':dist})

选项2:如果有大数据帧,循环可能不会太糟糕:

from scipy.spatial.distance import cdist

ret = []
for i in set(df['rank']):
    this_group = df['rank']==i
    other_groups = df['rank'].between(i,i+n, inclusive=False)
    t = df.loc[this_group,['x','y','z']].values
    o = df.loc[other_groups,['x','y','z']].values
    ret.append(cdist(t,o).ravel())

dist = np.concatenate(ret)

成员
组是否总是具有相同的行数?不,不幸的是,它们没有。为了方便起见,我制作了一个人为的示例,使每个组拥有相同数量的成员资格。您的数据有多大?也许交叉合并就可以了。它不是很大。实际上,我正在构建一个图,上面的
矩阵
用于计算邻接矩阵。我的图有大约4000个节点;但是我有很多这样的独立图(~1000个图)。然而,我正在努力缩短任何
ms
的时间。以前我对交叉合并的经验是,它相当慢。
df.query('rank\ux
from scipy.spatial.distance import cdist

ret = []
for i in set(df['rank']):
    this_group = df['rank']==i
    other_groups = df['rank'].between(i,i+n, inclusive=False)
    t = df.loc[this_group,['x','y','z']].values
    o = df.loc[other_groups,['x','y','z']].values
    ret.append(cdist(t,o).ravel())

dist = np.concatenate(ret)