簡體   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