计算路径/轨迹中有多少部分处于另外两条轨迹之间

7
在广义上,我正在尝试计算红色路径/轨迹有多少落在许多不同试验的黑色路径之间(见下图)。 我圈出了一些示例,其中对于(0,1,3),大约30-40%的红色路径落在两个黑色路径之间,但对于(2,1,3),只有约1-2%的红色路径落在两个黑色路径之间。

enter image description here

我有两个数据框,df_R和df_H。
df_R包含红色路径的位置数据(在X和Z中)。请注意,X和Z都是位置/空间数据。这些数据没有类似于日期/时间的索引。还要注意,这是来自Unity应用程序的2D数据(由于某种原因,X和Z等效于Y和X)。在两个数据框中,所有路径/轨迹长度均为1000个点。
df_R的预览:
    (0, 1, 1)_mean_X  (0, 1, 1)_mean_Z  ...  (2, 2, 3)_mean_X  (2, 2, 3)_mean_Z
0         -15.856713          5.002617  ...        -15.600160         -5.010470
1         -15.831320          5.003529  ...        -15.566172         -5.012251
2         -15.805927          5.004441  ...        -15.532184         -5.014032
3         -15.780534          5.005353  ...        -15.498196         -5.015814
4         -15.755141          5.006265  ...        -15.464208         -5.017595
..               ...               ...  ...               ...               ...
95        -12.818362          5.429729  ...        -12.391177         -5.391595
96        -12.783905          5.437335  ...        -12.357563         -5.396919
97        -12.749456          5.444990  ...        -12.323950         -5.402243
98        -12.715017          5.452697  ...        -12.290336         -5.407567
99        -12.680594          5.460469  ...        -12.256722         -5.412891

df_H包含黑色路径的位置数据,其中包括X和Z的“顶部”和“底部”列,对应于每个图中的两条黑色路径。

df_H的预览:

    (0, 1, 1)_top_X  (0, 1, 1)_bottom_X  ...  (2, 2, 3)_top_Z  (2, 2, 3)_bottom_Z
0        -16.000000          -16.000000  ...        -5.000000           -5.000000
1        -16.000000          -16.000000  ...        -5.000000           -5.000000
2        -16.000000          -16.000000  ...        -5.000000           -5.000000
3        -16.000000          -16.000000  ...        -5.000000           -5.000000
4        -16.000000          -16.000000  ...        -5.000000           -5.000000
..              ...                 ...  ...              ...                 ...
95       -15.000971          -15.417215  ...        -4.993461           -5.011372
96       -14.979947          -15.402014  ...        -4.993399           -5.013007
97       -14.957949          -15.385840  ...        -4.993291           -5.014463
98       -14.934171          -15.368649  ...        -4.993186           -5.015692
99       -14.908484          -15.349371  ...        -4.993069           -5.016940

我需要确认df_R中的X/Z值是否在df_H中的X/Z值范围内。然而,解决方案不能依赖于时间或索引(或逐行比较)。我一直试图实现这个功能,但卡住了。这是我一直在尝试的方法,但它不起作用,因为它依赖于时间。
import pandas as pd
import numpy as np

def CI_analysis(df_H, df_R):
    
    # separate X & Z 
    df_H_top_X = df_H.filter(regex='top_X')
    df_H_bottom_X = df_H.filter(regex='bottom_X')
    
    df_H_top_Z = df_H.filter(regex='top_Z')
    df_H_bottom_Z = df_H.filter(regex='bottom_Z')
    
    df_R_X = CI_raycast.filter(regex='mean_X') 
    df_R_Z = CI_raycast.filter(regex='mean_Z') 
    
    # check if X is within the range of top & bottom X
    CI_inside_X = pd.DataFrame()
    for col in df_R_X:
        temp = []
        c = 0
        for i, val in df_R_X[col].iteritems():
            if (val < df_H_top_X.iloc[i,c]) & (val > df_H_bottom_X.iloc[i,c]):
                temp.append(1)
            else: 
                temp.append(0)
        CI_inside_X[col] = temp
        c = c+1

    # check if Z is within the range of top & bottom Z
    CI_inside_Z = pd.DataFrame()
    for col in df_R_Z:
        temp = []
        # print(col)
        c = 0
        for i, val in df_R_Z[col].iteritems():
            if (val < df_H_top_Z.iloc[i,c]) & (val > df_H_bottom_Z.iloc[i,c]):
                temp.append(1)
            else: 
                temp.append(0)
        CI_inside_Z[col] = temp
        c = c+1

    # Check if X & Z were both in-between the top & bottom trajectories
    CI_inside = pd.DataFrame()
    for col in CI_inside_X:
        temp = []
        c = 0
        for i,row in CI_inside_X[col].iteritems(): 
            if (row == 1) & (CI_inside_Z.iloc[i,c] == 1):
                temp.append(1)
            else: 
                temp.append(0)
        CI_inside[col] = temp
        c = c+1
    
    CI_inside_avg = pd.DataFrame(CI_inside.mean(axis=0)).transpose() 
    
    return CI_inside_X, CI_inside_Z, CI_inside, CI_inside_avg  

最后,这里是用随机数复制df_R和df_H两个数据框的代码:
df_R_cols = ['(0, 1, 1)_mean_X', '(0, 1, 1)_mean_Z', '(0, 1, 2)_mean_X',
       '(0, 1, 2)_mean_Z', '(0, 1, 3)_mean_X', '(0, 1, 3)_mean_Z',
       '(0, 2, 1)_mean_X', '(0, 2, 1)_mean_Z', '(0, 2, 2)_mean_X',
       '(0, 2, 2)_mean_Z', '(0, 2, 3)_mean_X', '(0, 2, 3)_mean_Z',
       '(1, 1, 1)_mean_X', '(1, 1, 1)_mean_Z', '(1, 1, 2)_mean_X',
       '(1, 1, 2)_mean_Z', '(1, 1, 3)_mean_X', '(1, 1, 3)_mean_Z',
       '(1, 2, 1)_mean_X', '(1, 2, 1)_mean_Z', '(1, 2, 2)_mean_X',
       '(1, 2, 2)_mean_Z', '(1, 2, 3)_mean_X', '(1, 2, 3)_mean_Z',
       '(2, 1, 1)_mean_X', '(2, 1, 1)_mean_Z', '(2, 1, 2)_mean_X',
       '(2, 1, 2)_mean_Z', '(2, 1, 3)_mean_X', '(2, 1, 3)_mean_Z',
       '(2, 2, 1)_mean_X', '(2, 2, 1)_mean_Z', '(2, 2, 2)_mean_X',
       '(2, 2, 2)_mean_Z', '(2, 2, 3)_mean_X', '(2, 2, 3)_mean_Z'] 

df_H_cols = ['(0, 1, 1)_top_X', '(0, 1, 1)_bottom_X', '(0, 1, 1)_top_Z',
       '(0, 1, 1)_bottom_Z', '(0, 1, 2)_top_X', '(0, 1, 2)_bottom_X',
       '(0, 1, 2)_top_Z', '(0, 1, 2)_bottom_Z', '(0, 1, 3)_top_X',
       '(0, 1, 3)_bottom_X', '(0, 1, 3)_top_Z', '(0, 1, 3)_bottom_Z',
       '(0, 2, 1)_top_X', '(0, 2, 1)_bottom_X', '(0, 2, 1)_top_Z',
       '(0, 2, 1)_bottom_Z', '(0, 2, 2)_top_X', '(0, 2, 2)_bottom_X',
       '(0, 2, 2)_top_Z', '(0, 2, 2)_bottom_Z', '(0, 2, 3)_top_X',
       '(0, 2, 3)_bottom_X', '(0, 2, 3)_top_Z', '(0, 2, 3)_bottom_Z',
       '(1, 1, 1)_top_X', '(1, 1, 1)_bottom_X', '(1, 1, 1)_top_Z',
       '(1, 1, 1)_bottom_Z', '(1, 1, 2)_top_X', '(1, 1, 2)_bottom_X',
       '(1, 1, 2)_top_Z', '(1, 1, 2)_bottom_Z', '(1, 1, 3)_top_X',
       '(1, 1, 3)_bottom_X', '(1, 1, 3)_top_Z', '(1, 1, 3)_bottom_Z',
       '(1, 2, 1)_top_X', '(1, 2, 1)_bottom_X', '(1, 2, 1)_top_Z',
       '(1, 2, 1)_bottom_Z', '(1, 2, 2)_top_X', '(1, 2, 2)_bottom_X',
       '(1, 2, 2)_top_Z', '(1, 2, 2)_bottom_Z', '(1, 2, 3)_top_X',
       '(1, 2, 3)_bottom_X', '(1, 2, 3)_top_Z', '(1, 2, 3)_bottom_Z',
       '(2, 1, 1)_top_X', '(2, 1, 1)_bottom_X', '(2, 1, 1)_top_Z',
       '(2, 1, 1)_bottom_Z', '(2, 1, 2)_top_X', '(2, 1, 2)_bottom_X',
       '(2, 1, 2)_top_Z', '(2, 1, 2)_bottom_Z', '(2, 1, 3)_top_X',
       '(2, 1, 3)_bottom_X', '(2, 1, 3)_top_Z', '(2, 1, 3)_bottom_Z',
       '(2, 2, 1)_top_X', '(2, 2, 1)_bottom_X', '(2, 2, 1)_top_Z',
       '(2, 2, 1)_bottom_Z', '(2, 2, 2)_top_X', '(2, 2, 2)_bottom_X',
       '(2, 2, 2)_top_Z', '(2, 2, 2)_bottom_Z', '(2, 2, 3)_top_X',
       '(2, 2, 3)_bottom_X', '(2, 2, 3)_top_Z', '(2, 2, 3)_bottom_Z']

df_R = pd.DataFrame(np.random.randint(0,100,size=(1000, 36)), columns=df_R_cols)
df_H = pd.DataFrame(np.random.randint(0,100,size=(1000, 72)), columns=df_H_cols)

1
你可能想考虑使用Shapely和/或Geopandas来完成这个任务。这是一个已经具备形状、面积、交叉等概念的软件包,但我不知道你的任务是否可行。 - anon01
@Tommy 实际上,我认为每对X值在Y的相同值处并不一定都是相同的,因为该应用程序只以50Hz采样2D位置。在df_R中,mean_X和mean_Z分别是“x_red”和“z_red”。在df_H中,top_X和top_Z分别是x_black1和z_black1,bottom_X和bottom_Z分别是x_black2和z_black2。所有轨迹长度均为1000个点。 - CentauriAurelius
我考虑的方法是一个近似方法,如下所示。将Y(垂直)空间离散化为水平桶。例如,如果Y轴从0到100,则为0到.01,.01到.02等(这将是10000个桶)。然后,根据Y将所有X值放入其水平桶中。最后,您寻找的比率是x_black1 <= x_Red <= x_black2的行数/总桶数。如果您的所有Y值已对齐,则应该不难做到这一点?最好在pandas datatrames之外完成此操作。 - Tommy
即使是一个简单的字典或桶列表:[(x_b1, x_r, x_b2),....],其中每个3元组都是为相同的Y值而设计的;然后计算比率。例如:读取您的数据帧并将它们转储到这个桶结构中。 - Tommy
1
这是我为您制作的图片 https://imgur.com/a/32XDRvK 每个桶的索引将类似于 floor(Yval / bucket_size) 或类似的内容。 - Tommy
显示剩余13条评论
3个回答

2

只是一个想法

如果我正确理解了讨论,问题在于数据是在不同的点进行采样的。因此,您不能仅比较每行的值。有时底线会与顶部线交换。

我的想法现在是将黑色轨迹插值为与红色轨迹相同的x值。我的答案集中在这个想法上。我从之前的答案中借用了一些代码来迭代数据集。

    df_H = pd.read_pickle('df_H.pickle')
    df_R = pd.read_pickle('df_R.pickle')
    dfh_groups = [df_H.columns[x:x + 4] for x in range(0, len(df_H.columns), 4)]
    dfr_groups = [df_R.columns[x:x + 2] for x in range(0, len(df_R.columns), 2)]
    df_result = pd.DataFrame(columns=['Percentage'])

    for i in range(len(dfr_groups)):

        label = dfr_groups[i][0].split('_')[0]

        X_R = df_R[dfr_groups[i][0]].to_numpy()
        Y_R = df_R[dfr_groups[i][1]].to_numpy()
        X_H_Top = df_H[dfh_groups[i][0]].to_numpy()
        Y_H_Top = df_H[dfh_groups[i][1]].to_numpy()
        X_H_Bottom = df_H[dfh_groups[i][2]].to_numpy()
        Y_H_Bottom = df_H[dfh_groups[i][3]].to_numpy()

        # Interpolate df_H to match the data points from df_R
        bottom = interpolate.interp1d(X_H_Bottom,Y_H_Bottom)
        top = interpolate.interp1d(X_H_Top,Y_H_Top)

        # Respect the interpolation boundaries, so drop every row not in range from X_H_(Bottom/Top)
        X_H_Bottom = X_R[(X_R > np.amin(X_H_Bottom)) & (X_R < np.amax(X_H_Bottom))]
        X_H_Top = X_R[(X_R > np.amin(X_H_Top)) & (X_R < np.amax(X_H_Top))]
        minimal_X = np.intersect1d(X_H_Bottom, X_H_Top)

        # Calculate the new values an the data points from df_R
        Y_I_Bottom = bottom(minimal_X)
        Y_I_Top = top(minimal_X)

        #Plot
        '''
        plt.plot(X_R, Y_R,'r-',minimal_X, Y_I_Bottom,'k-', minimal_X, Y_I_Top,'k-')
        plt.show()
        '''

        # Count datapoints of df_R within bottom and top
        minimal_x_idx = 0
        nr_points_within = 0
        for i in range(0,len(X_R)):
            if minimal_x_idx >= len(minimal_X):
                break
            elif X_R[i] != minimal_X[minimal_x_idx]:
                continue
            else:
                # Check if datapoint within even if bottom and top changed
                if (Y_R[i] > np.amin(Y_I_Bottom[minimal_x_idx]) and  Y_R[i] < np.amax(Y_I_Top[minimal_x_idx]))\
                        or (Y_R[i] < np.amin(Y_I_Bottom[minimal_x_idx]) and  Y_R[i] > np.amax(Y_I_Top[minimal_x_idx])):
                    nr_points_within += 1
                minimal_x_idx += 1

        # Depends on definition if points outside of interpolation range should be count as outside or be dropped
        percent_within = (nr_points_within * 100) / len(minimal_X)
        df_result.loc[label] = [percent_within]
    print(df_result)

我认为并且希望有更加优雅的方式来实现这个,特别是最后的for循环。

我测试了一下,它工作得相当不错,至少乍一看是这样。对于您标记的内容,我得到了71.8%(0,1,3)和0.8%(2,1,3)。

我只是比较了插值后的每一行。但是在这一点上,你可以再进一步。例如,您可以获得样条插值系数,然后计算轨迹的交点。因此,您可以计算投影到x轴的百分比或者确切地说是落入轨迹内的长度百分比。也许还有一个漂亮的误差估计。我希望这能帮助一点。

基于评论的更详细的解释

首先,我将您的Z轴重命名为我的变量和解释中的Y轴,希望这不会太令人困惑。使用scipy函数interp1d进行底部/顶部轨迹的样条插值。基本上,这意味着我基于底部和顶部轨迹的给定X/Y值来模拟两个数学函数。这些函数分别为底部或顶部返回连续的输出。在每个X值上,我可以从轨迹中获取Y值,即使对于数据中不存在的X值也可以。这是通过所谓的样条插值完成的。在数据中的每个X / Y值对之间计算一条线(m * x + t)。您还可以使用关键字'cubic',然后会计算一个二次多项式(ax ^ 2 + bx + c)。现在,通过这个模型,我可以查看底部和顶部轨迹在红色轨迹给定的X值处具有哪些值。

但是,这种方法有其限制,因此我需要放弃一些值。插值仅在数据集给定的X值的最小值和最大值之间定义。例如,如果红色轨迹具有小于数据集中底部轨迹的最小X值x1,则无法获取x1的底部轨迹的相应Y值,因为在x1处未定义底部轨迹的插值。因此,我限制自己在已知所有轨迹且我的插值在底部和顶部都定义良好的范围内。

PS.: 这是我对整个数据集的输出:

           Percentage
(0, 1, 1)    3.427419
(0, 1, 2)   76.488396
(0, 1, 3)   71.802618
(0, 2, 1)    6.889564
(0, 2, 2)   16.330645
(0, 2, 3)   59.233098
(1, 1, 1)   13.373860
(1, 1, 2)   45.262097
(1, 1, 3)   91.084093
(1, 2, 1)    0.505051
(1, 2, 2)    1.010101
(1, 2, 3)   41.253792
(2, 1, 1)    4.853387
(2, 1, 2)   12.916246
(2, 1, 3)    0.808081
(2, 2, 1)    0.101112
(2, 2, 2)    0.708502
(2, 2, 3)   88.810484


是的,这返回了看起来有意义的值!当你“删除不在X_H_(底部/顶部)范围内的每一行”时,你能解释一下你在做什么吗?将黑色轨迹插值到与红色轨迹相同的x值是什么意思? - CentauriAurelius
我在答案末尾加了一些解释,基于你的评论。希望这能稍微澄清一下。 - moritz
你的解释非常有帮助,太棒了,谢谢。您是否可以编辑您的代码,将您的解决方案应用于整个数据集,并一次输出所有百分比? - CentauriAurelius
我更新了我的代码。现在可以为所有集合生成百分比。 - moritz
你的代码针对给定的数据产生了有意义的值,因此我授予了你赏金。之前的答案也帮助更全面地阐明了问题,比我能做到的更好。向大家干杯。 - CentauriAurelius

2
这个解决方案以更高效的方式实现了OP的代码,并且做到了所要求的,但并非所想要的。 虽然这个解决方案没有提供所需的结果,但在与OP讨论后,我们决定保留这个答案,因为它有助于澄清所需的结果。 也许有人可以从这里提供的内容中继续努力,达到下一步。我稍后会再次尝试。
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

# create a reproducible dataframe
np.random.seed(365)
df_R = pd.DataFrame(np.random.randint(0,100,size=(1000, 36)), columns=df_R_cols)
df_H = pd.DataFrame(np.random.randint(0,100,size=(1000, 72)), columns=df_H_cols)

# create groups of column names: 18 groups
dfh_groups = [df_H.columns[x:x+4] for x in range(0, len(df_H.columns), 4)]
dfr_groups = [df_R.columns[x:x+2] for x in range(0, len(df_R.columns), 2)]

# create empty lists for pandas Series
x_series = list()
z_series = list()
both_series = list()

for i in range(len(dfr_groups)):

    # print the groups
    print(dfr_groups[i])
    print(dfh_groups[i])
    
    # extract the groups of column names
    rx, rz = dfr_groups[i]
    htx, hbx, htz, hbz = dfh_groups[i]
    
    # check if _mean is between _top & _bottom
    x_between = (df_R.loc[:, rx] < df_H.loc[:, htx]) & (df_R.loc[:, rx] > df_H.loc[:, hbx])
    z_between = (df_R.loc[:, rz] < df_H.loc[:, htz]) & (df_R.loc[:, rz] > df_H.loc[:, hbz])
    
    # check if x & z meet the criteria
    both_between = x_between & z_between
    
    # name the pandas Series
    name = rx.split('_')[0]
    x_between.rename(f'{name}_x', inplace=True)
    z_between.rename(f'{name}_z', inplace=True)
    both_between.rename(f'{name}_xz', inplace=True)
    
    # append Series to lists
    x_series.append(x_between)
    z_series.append(z_between)
    both_series.append(both_between)

    # the following section of the loop is only used for visualization
    # it is not necessary, other that for the plots

    # plot
    fig, (ax1, ax2) = plt.subplots(ncols=2, figsize=(16, 6))
    ax1.plot(df_R.loc[:, rz], df_R.loc[:, rx], label='mid')
    ax1.plot(df_H.loc[:, htz], df_H.loc[:, htx], label='top')
    ax1.plot(df_H.loc[:, hbz], df_H.loc[:, hbx], label='bottom')
    ax1.set_title(f'{name}\nboth: {both_between.mean()}\nx: {x_between.mean()}\nz: {z_between.mean()}')
    ax1.set_xlabel('Z-val')
    ax1.set_ylabel('X-val')
    ax1.legend()
    
    # plot x, z, and mean with respect to the index
    ax2.plot(df_R.index, df_R.loc[:, rx], label='x_mean')
    ax2.plot(df_H.index, df_H.loc[:, htx], label='x_top')
    ax2.plot(df_H.index, df_H.loc[:, hbx], label='x_bot')
    
    ax2.plot(df_R.index, df_R.loc[:, rz], label='z_mean')
    ax2.plot(df_H.index, df_H.loc[:, htz], label='z_top')
    ax2.plot(df_H.index, df_H.loc[:, hbz], label='z_bot')
    
    ax2.set_title('top, bottom and mean plotted with the x-axis as the index')
    ax2.legend()
    plt.show()
    

# concat all the Series into dataframes and set the type to int
df_x_between = pd.concat(x_series, axis=1).astype(int)
df_z_between = pd.concat(z_series, axis=1).astype(int)
df_both_between = pd.concat(both_series, axis=1).astype(int)

# calculate the mean
df_both_between.mean(axis=0).to_frame().T
  • 这张图是用OP提供的真实数据生成的。
  • 下面的图表展示了为什么当前实现的条件不能按预期工作。
    • 例如,来自OP的(val < df_H_top_X.iloc[i,c]) & (val > df_H_bottom_X.iloc[i,c])已经在上面用x_between实现了。
    • 右边的图表显示指定的条件无法确定mid是否在topbottom之间,就像左边的图表所示。

enter image description here


@CentauriAurelius 这对于测试数据有效。但是目前为止,df_x_betweendf_z_between得到了什么?看起来正确吗? - Trenton McKinney
这两个数据框中有一些1,但比我预期的要少。我尝试将您添加到stackoverflow聊天中,以避免在评论中讨论,因为我在另一篇帖子中收到了警告。 - CentauriAurelius
让我们在聊天中继续这个讨论 - Trenton McKinney
1
图表很好地展示了手头的问题。本质上,这是一个视觉问题:在二维平面上给定两条“平行”的黑色路径,红色路径内覆盖了多少百分比是一个几何问题。这实际上完全没有考虑时间因素。另一个问题是,在给定时间点上,给定三个点b_top、b_bottom、r_mean,它是否处于中间位置,这是一个非常简单的不同问题。也许,问题背后的真正动机是什么,这样我们才能解决所需求的内容? - supercooler8
1
我从你的答案中借了一些代码用在我的项目中,省去了很多思考时间。希望以点赞作为租借费是可以的。谢谢! - moritz
显示剩余2条评论

1

我将采取稍微不同的路线。这还很粗糙,欢迎批评/建议!(为什么我在大声喊叫?!)

 

如果可能的话,将所有元组放入可迭代对象中:
a_rng = range(3)
b_rng = range(1, 3)
c_rng = range(1, 4)
all_my_tuples = [(a, b, c) for a in a_rng for b in b_rng for c in c_rng]

使用f-strings列出推导式:

df_R_cols = [f"{x}_mean_{e}" for x in all_my_tuples for e in ["X","Z",]]
df_H_cols = [f"{x}_{pos}_{e}" for x in all_my_tuples for e in ["X","Z",] for pos in ["top", "bottom",]]

创建巨大的数据框。
df_R_H = pd.merge(df_R, df_H, left_index=True, right_index=True)

使用 pandas.query() 创建并执行动态查询字符串:
使用 all_my_tuples 作为索引创建输出数据帧。
df_fin = pd.DataFrame(index = map(str, all_my_tuples), columns=["n_found",])

# Iterate tuple elements
for t in all_my_tuples:
    # Create query list.
    qry_ = []
    # Repeat same query creation process for X and Z.
    for xz in ["X", "Z"]:
        qry_.append(f"(`{t}_mean_{xz}` < `{t}_top_{xz}` & `{t}_mean_{xz}` > `{t}_bottom_{xz}`)")

    # Join to create full query and execute into new dataframe
    qry = " & ".join(qry_)
    # print(qry)
    dft = df_R_H.query(qry)

    # Update dataframe with row count
    if not (dft) is None:
        df_fin.loc[f"{t}", "n_found"] = dft.shape[0]
    else:
        df_fin.loc[f"{t}", "n_found"] = 0

然后将其中一个数据框的行数作为除数。

df_fin["n_mean"] = df_fin.loc[:, "n_found"].apply(lambda q: q / df_R.shape[0])

输出类似以下内容:
          n_found  n_mean
(0, 1, 1)      27   0.027
(0, 1, 2)      34   0.034
(0, 1, 3)      25   0.025
(0, 2, 1)      23   0.023
(0, 2, 2)      31   0.031
(0, 2, 3)      29   0.029
(1, 1, 1)      22   0.022
(1, 1, 2)      23   0.023
(1, 1, 3)      22   0.022
(1, 2, 1)      21   0.021
(1, 2, 2)      22   0.022
(1, 2, 3)      27   0.027
(2, 1, 1)      29   0.029
(2, 1, 2)      35   0.035
(2, 1, 3)      25   0.025
(2, 2, 1)      29   0.029
(2, 2, 2)      23   0.023
(2, 2, 3)      32   0.032

刚试了一下 - 在 df_fin 中,对于 (0, 1, 3),我得到了一个均值为 .022 的值,但是从图中可以清楚地看到,超过 2.2% 的红色轨迹落在了两个黑色轨迹之内。我认为解决方案将要求按照 @tommy 建议的方式对 X 或 Z 值进行分桶处理,而不是逐行计算。 - CentauriAurelius
我可以通过聊天向您发送指向 GitHub 上腌制数据帧的链接。 - CentauriAurelius
如果我查询(0、1、3)的Z值,我只得到18个结果。从这18个结果来看,似乎没有任何X约束条件适用。除非我读取数据有误。截图-> https://i.imgur.com/AgWqzrm.png - Mark Moretto
所以,这与顶部和底部没有太大关系?我只是想确保我理解了,我认为我理解了,但可能是这样的:top_Z < mean_Z < bottom_Ztop_Z > mean_Z > bottom_Z。在任何情况下,它都不能是top_Z > mean_Z < bottom_Ztop_Z < mean_Z > bottom_Z,因为这将使其至少超出一个条件的范围。 - Mark Moretto
是的,对于不同的组(例如(0,1,3)与(2,2,3)),顶部和底部有时会“切换”。但是,在每个组内部,它们不会切换。因此,我想也许可以为每个组添加一个检查,以查看顶部与底部轨迹中X的大小关系,然后应用相应的条件。 - CentauriAurelius
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接