【问题标题】:Pandas columns line intersection熊猫列线交叉点
【发布时间】:2017-12-05 14:26:13
【问题描述】:

我有一个 pandas 数据框,其中每一列代表从 1 到 0 的下降线的 y 值,索引代表 x 值。现在我有兴趣找到这些线与给定常数(线性插值)之间的交点。

所需输出的示例:

>>> df = pd.DataFrame({'y1': [1, .7, .4, .1, 0],
                       'y2': [1, .9, .7, .3, 0],
                       'y3': [1, .6, .3, .2, 0],
                       'y4': [1, .7, .5, .3, 0]}, index=[0, 10, 20, 30, 40])
>>> xs = get_intersection(df, .5)
>>> xs
{'x1': 16.6667,  # = scipy.interpolate.interp1d([.7, .4], [10, 20])(.5)
 'x2': 25.0,     # =                   interp1d([.7, .3], [20, 30])(.5)
 'x3': 13.3332,  # =                   interp1d([.6, .3], [10, 20])(.5)
 'x4': 20}       # No interpolation required

我的数据大约包含 400 行和 50.000 列。


可能的解决方案:

我找到了this SO answer,它使用以下方法找到两条线之间的交点:

idx = np.argwhere(np.diff(np.sign(f - g)) != 0).reshape(-1) + 0

我认为这可以调整为适用于我的数据框,但我不确定如何从这里开始:

>>> idx = np.argwhere(np.diff(np.sign(df - .5), axis=0) != 0)
>>> idx
array([[1, 0],
       [1, 2],
       [1, 3],
       [2, 1],
       [2, 3]], dtype=int64)

由于人们似乎误解了这个问题,我有兴趣找到以下几点:

可以通过对最近的两个点进行线性插值来找到。


解决方案: B.M.让我朝着正确的方向迈出了一步:

def get_intersection(df, c):
    dfind = len(df) - df.loc[::-1].apply(np.searchsorted, args=(c,), raw=True)

    result = {}
    for i, v in enumerate(dfind):
        result[df.columns.values[i]] = interp1d([df.iloc[v][i], df.iloc[v - 1][i]], [df.index[v], df.index[v - 1]])(.5)

    return result


>>> get_intersection(df, .5)
{'y1': array(16.666666666666668), 'y2': array(25.0), 'y3': array(13.333333333333332), 'y4': array(20.0)}

【问题讨论】:

  • 我很困惑,你现在想从我们这里得到什么?
  • 我不确定如何使用idx 来查找ys 的值。或者,如果得到idx 的方法不必要地复杂,另一种计算ys 的方法。
  • 您可以通过dfind=len(df)-df.loc[::-1].apply(np.searchsorted,args=(0.5,),raw=True)找到第一个点的索引。 Atter 通过循环来完成。
  • 你,这行得通!

标签: python pandas line-intersection


【解决方案1】:

由于您需要一维函数 (interp1d),因此循环与 pandas 函数一样清晰、易于阅读和速度。使用 np.searchsorted 找到好的部分:

d = dict()
ind=df.index.values
for k,v in df.iteritems():
    y=v.values
    i=len(y)-np.searchsorted(y[::-1],0.5) #indices
    sl = slice(i-1,i+1)
    d[k]= +scipy.interpolate.interp1d(v[sl],ind[sl])(.5)

print (pd.Series(d))

# y1    16.666667
# y2    25.000000
# y3    13.333333
# y4    20.000000
# dtype: float64

如果不存在交点,则可能必须对此进行调整。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-04-09
    • 2019-10-30
    • 2016-05-17
    • 2021-03-06
    • 2020-09-05
    • 1970-01-01
    • 2020-03-16
    • 1970-01-01
    相关资源
    最近更新 更多