繁体   English   中英

如何在执行 df.apply() 时访问 pandas lambda 函数中的前一行值或获取每行的索引

[英]How to access previous row value in pandas lambda function or get the index of each row when doing df.apply()

最后看最初的问题。

我有一个像这样的数据框

df = pd.DataFrame({'Persons':[10,20,30], 'Bill':[110,240,365], 'Guests':[12,25,29],'Visitors':[15,23,27]})
df

Persons     Bill    Guests  Visitors
10          110     12      15
20          240     25      23
30          365     29      27

我想要一个像下面这样的数据框


Persons     Bill    Guests  Visitors Charge  VisitorsCharge
10          110     12      15       136     175
20          240     25      23       302.5   277.5
30          365     29      27       352.5   327.5

这里的Charge是对应于以People & Bill列作为参考的Guests的插值。

如果我们占据第一排,我们说 10 People将累积为 110 的Bill ,而 20 People将累积为 240 的Bill 。那么,12 位Guests产生的Charge是多少?

公式如下

第 1 行

import scipy.stats as stats
result = stats.linregress([10,20],[110,240])
slope = result.slope #extract the slope of the interpolation curve
intercept = result.intercept #extract the intercept of the interpolation curve
interpolatedValue  = slope*12 + intercept #interpolate the value
interpolatedValue

第 2 行

import scipy.stats as stats
result = stats.linregress([20,30],[240,365])
slope = result.slope #extract the slope of the interpolation curve
intercept = result.intercept #extract the intercept of the interpolation curve
interpolatedValue  = slope*25 + intercept #interpolate the value
interpolatedValue

第 3 行

import scipy.stats as stats
result = stats.linregress([20,30],[240,365])
slope = result.slope #extract the slope of the interpolation curve
intercept = result.intercept #extract the intercept of the interpolation curve
interpolatedValue  = slope*29 + intercept #interpolate the value
interpolatedValue

对于除最后一行之外的每一行,我们必须使用当前和下一行的值来获得我们的结果。

但是,当我们到达最后一行时,我们将没有“下一个”行。 因此,我们连接当前行和前一行值。

我们也用同样的方法来计算VisitorsCharge 但在这里,我们使用Vistors列值与“斜率”相乘

一个函数可以解决这个问题。 但是,使用 lambda 函数,我无法访问上一行和下一行。 使用 df.apply,我无法在应用函数时找出每一行的索引。 我该怎么做?

最初的问题

我有一个像这样的数据框

A   B   
1   100
2   200
3   300

我想要一个像下面这样的数据框

A   B   C
1   100 '1-2-100-200'   
2   200 '2-3-200-300'
3   300 '2-3-200-300'

注意。 初始问题的解决方案。 有关新问题的答案,请参见此处

您可以使用shiftffill

a = df['A'].astype(str)
b = df['B'].astype(str)
s = a+'-'+a.shift(-1)+'-'+b+'-'+b.shift(-1)
df['C'] = s.ffill()

任意列数的泛化:

def cat(s, sep='-'):
    s = s.astype(str)
    return s+sep+s.shift(-1)

df['C'] = df.apply(cat).ffill().agg('-'.join, axis=1)

输出:

   A    B            C
0  1  100  1-2-100-200
1  2  200  2-3-200-300
2  3  300  2-3-200-300

我认为这就是你想要的:

import scipy.stats as stats

def compute(i, n=2):
    j = min(i, df.index[len(df)-n])
    idx = df.index[j:j+n]
    result = stats.linregress(df.loc[idx, 'Persons'], df.loc[idx, 'Bill'])
    slope = result.slope
    intercept = result.intercept
    return slope*df.loc[i, 'Guests'] + intercept

df['Charge'] = [compute(i) for i in df.index]
# or
# df['Charge'] = df.index.to_series().apply(compute)

输出:

   Persons  Bill  Guests  Charge
0       10   110      12   136.0
1       20   240      25   302.5
2       30   365      29   352.5

尝试这个:

import scipy.stats as stats

df['next_persons'] = df.Persons.shift(-1)
df['next_bill'] = df.Bill.shift(-1)

def your_interpolation_func(x, y, z): 
    result = stats.linregress(np.array(x), np.array(y))
    return result.slope*z + result.intercept

df['charge'] = df.apply(lambda row: your_interpolation_func(
    [row.Persons, row.next_persons],
    [row.Bill, row.next_bill],
    row.Guests), axis=1)

输出:

df

    Persons Bill    Guests  next_persons    next_bill   charge
0   10  110 12  20.0    240.0   136.0
1   20  240 25  30.0    365.0   302.5
2   30  365 29  NaN NaN NaN

最后一行中的NaN是因为最后一行没有任何下一个数字。 您可以将该函数应用于df.iloc[:-1]以避免这种情况。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM