亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

對組對象應用VS轉換

對組對象應用VS轉換

冉冉說 2019-07-16 15:40:59
對組對象應用VS轉換考慮以下數據:     A      B         C         D0  foo    one  0.162003  0.0874691  bar    one -1.156319 -1.5262722  foo    two  0.833892 -1.6663043  bar  three -2.026673 -0.3220574  foo    two  0.411452 -0.9543715  bar    two  0.765878 -0.0959686  foo    one -0.654890  0.6780917  foo  three -1.789842 -1.130922以下命令起作用:> df.groupby('A').apply(lambda x: (x['C'] - x['D']))> df.groupby('A').apply(lambda x: (x['C'] - x['D']).mean())但下列任何一項工作都沒有:> df.groupby('A').transform(lambda x: (x['C'] - x['D']))ValueError: could not broadcast input array from shape (5) into shape (5,3)> df.groupby('A').transform(lambda x: (x['C'] - x['D']).mean()) TypeError: cannot concatenate a non-NDFrame object為什么? 關于文檔的示例似乎意味著transform在組中允許進行逐行操作處理:# Note that the following suggests row-wise operation (x.mean is the column mean)zscore = lambda x: (x - x.mean()) / x.std()transformed = ts.groupby(key).transform(zscore)換句話說,我認為轉換本質上是一種特定類型的應用(不聚合)。我哪里錯了?以下是上述原始數據的構造,供參考:df = pd.DataFrame({'A' : ['foo', 'bar', 'foo', 'bar',                          'foo', 'bar', 'foo', 'foo'],                   'B' : ['one', 'one', 'two', 'three',                         'two', 'two', 'one', 'three'],                   'C' : randn(8), 'D' : randn(8)})
查看完整描述

3 回答

?
慕村225694

TA貢獻1880條經驗 獲得超4個贊


我同樣感到困惑.transform手術與手術.apply我找到了一些關于這個問題的答案。這個答案例如,非常有用。


到目前為止我的外賣是.transform將工作(或處理)Series(欄)與世隔絕..這意味著在你最后兩個電話里:


df.groupby('A').transform(lambda x: (x['C'] - x['D']))

df.groupby('A').transform(lambda x: (x['C'] - x['D']).mean())

你問.transform從兩列中獲取值,而“it”實際上并不同時“查看”這兩個列(可以這么說)。transform將逐一查看dataframe列,并返回由重復的標量組成的序列(或序列組)。len(input_column)時代。


所以這個標量,應該被.transform使Series是對輸入應用某種約簡函數的結果。Series(一次只能在一個系列/列上)。


請考慮這個示例(在您的dataframe上):


zscore = lambda x: (x - x.mean()) / x.std() # Note that it does not reference anything outside of 'x' and for transform 'x' is one column.

df.groupby('A').transform(zscore)

將產生:


       C      D

0  0.989  0.128

1 -0.478  0.489

2  0.889 -0.589

3 -0.671 -1.150

4  0.034 -0.285

5  1.149  0.662

6 -1.404 -0.907

7 -0.509  1.653

這與每次只在一列上使用它完全相同:


df.groupby('A')['C'].transform(zscore)

屈服:


0    0.989

1   -0.478

2    0.889

3   -0.671

4    0.034

5    1.149

6   -1.404

7   -0.509

請注意.apply在最后一個例子中(df.groupby('A')['C'].apply(zscore))將以完全相同的方式工作,但如果您嘗試在dataframe上使用它,則會失?。?/p>


df.groupby('A').apply(zscore)

給出錯誤:


ValueError: operands could not be broadcast together with shapes (6,) (2,)

所以還有別的地方.transform有用嗎?最簡單的情況是嘗試將約簡函數的結果分配回原始數據。


df['sum_C'] = df.groupby('A')['C'].transform(sum)

df.sort('A') # to clearly see the scalar ('sum') applies to the whole column of the group

屈服:


     A      B      C      D  sum_C

1  bar    one  1.998  0.593  3.973

3  bar  three  1.287 -0.639  3.973

5  bar    two  0.687 -1.027  3.973

4  foo    two  0.205  1.274  4.373

2  foo    two  0.128  0.924  4.373

6  foo    one  2.113 -0.516  4.373

7  foo  three  0.657 -1.179  4.373

0  foo    one  1.270  0.201  4.373

用同樣的方法.apply會給NaNs在……里面sum_C..因為.apply會退貨Series,它不知道如何廣播:


df.groupby('A')['C'].apply(sum)

給予:


A

bar    3.973

foo    4.373

在某些情況下.transform用于篩選數據:


df[df.groupby(['B'])['D'].transform(sum) < -1]


     A      B      C      D

3  bar  three  1.287 -0.639

7  foo  three  0.657 -1.179

我希望這能增加一點清晰度。


查看完整回答
反對 回復 2019-07-16
?
吃雞游戲

TA貢獻1829條經驗 獲得超7個贊

兩大區別apply和transform

之間有兩個主要的區別。transform和apply群方法


apply隱式地將每個組的所有列作為DataFrame到自定義函數,同時transform將每個組的每一列作為系列到自定義函數

傳遞給apply可以返回標量、系列或DataFrame(或numpy數組甚至列表)。傳遞給transform必須返回與組相同長度的序列(一維序列、數組或列表)。

所以,transform一次只做一個系列的作品apply同時處理整個DataFrame。


檢查自定義函數

檢查傳遞給您的自定義函數的輸入會有很大幫助。apply或transform.


實例

讓我們創建一些示例數據并檢查組,這樣您就可以看到我在說什么:


df = pd.DataFrame({'State':['Texas', 'Texas', 'Florida', 'Florida'], 

                   'a':[4,5,1,3], 'b':[6,10,3,11]})

df

讓我們創建一個簡單的自定義函數,它輸出隱式傳遞對象的類型,然后引發一個錯誤,以便可以停止執行。


def inspect(x):

    print(type(x))

    raise

現在讓我們把這個函數傳遞給groupbyapply和transform方法來查看傳遞給它的對象:


df.groupby('State').apply(inspect)


<class 'pandas.core.frame.DataFrame'>

<class 'pandas.core.frame.DataFrame'>

RuntimeError

如您所見,DataFrame被傳遞到inspect功能。您可能想知道為什么類型DataFrame被打印了兩次。第一組熊貓跑兩次。它這樣做是為了確定是否有一種快速的方法來完成計算。這是一個你不應該擔心的小細節。


現在,讓我們做同樣的事情transform


df.groupby('State').transform(inspect)

<class 'pandas.core.series.Series'>

<class 'pandas.core.series.Series'>

RuntimeError

它被傳遞了一個系列-一個完全不同的熊貓對象。


所以,transform一次只能使用一個系列。它不可能同時對兩列采取行動。所以,如果我們嘗試減去列a從…b在我們的自定義函數中,我們將得到一個錯誤transform..見下文:


def subtract_two(x):

    return x['a'] - x['b']


df.groupby('State').transform(subtract_two)

KeyError: ('a', 'occurred at index a')

當熊貓試圖找到系列索引時,我們得到了一個KeyErrora并不存在。您可以用apply因為它擁有整個DataFrame:


df.groupby('State').apply(subtract_two)


State     

Florida  2   -2

         3   -8

Texas    0   -2

         1   -5

dtype: int64

輸出是一個Series,由于保留了原始索引,所以有點混亂,但是我們可以訪問所有列。


顯示傳遞的熊貓對象

它可以幫助更多地顯示整個熊貓對象的自定義功能,這樣你就可以準確地看到你在操作什么。你可以用print語句,我喜歡使用display函數的IPython.display模塊,以便在jupyter筆記本中以HTML格式很好地輸出DataFrame:


from IPython.display import display

def subtract_two(x):

    display(x)

    return x['a'] - x['b']

截圖:enter image description here


轉換必須返回與組大小相同的一維序列。

另一個區別是transform必須返回與組大小相同的單維度序列。在這個特定的實例中,每個組有兩行,因此transform必須返回兩行的序列。如果沒有,則會引發錯誤:


def return_three(x):

    return np.array([1, 2, 3])


df.groupby('State').transform(return_three)

ValueError: transform must return a scalar value for each group

錯誤消息并不真正描述問題。必須返回與組長度相同的序列。所以,像這樣的函數會起作用:


def rand_group_len(x):

    return np.random.rand(len(x))


df.groupby('State').transform(rand_group_len)


          a         b

0  0.962070  0.151440

1  0.440956  0.782176

2  0.642218  0.483257

3  0.056047  0.238208

返回單個標量對象也適用于transform

如果您只從自定義函數返回一個標量,那么transform將用于組中的每一行:


def group_sum(x):

    return x.sum()


df.groupby('State').transform(group_sum)


   a   b

0  9  16

1  9  16

2  4  14

3  4  14


查看完整回答
反對 回復 2019-07-16
?
哆啦的時光機

TA貢獻1779條經驗 獲得超6個贊

我將用一個非常簡單的片段來說明兩者之間的區別:


test = pd.DataFrame({'id':[1,2,3,1,2,3,1,2,3], 'price':[1,2,3,2,3,1,3,1,2]})

grouping = test.groupby('id')['price']

DataFrame如下所示:


    id  price   

0   1   1   

1   2   2   

2   3   3   

3   1   2   

4   2   3   

5   3   1   

6   1   3   

7   2   1   

8   3   2   

本表中有3個客戶ID,每個客戶進行了三次交易,每次支付1,2,3美元。


現在,我想找到每個客戶的最低付款。有兩種方法:


使用apply:


Grouping.min()


回報如下:


id

1    1

2    1

3    1

Name: price, dtype: int64


pandas.core.series.Series # return type

Int64Index([1, 2, 3], dtype='int64', name='id') #The returned Series' index

# lenght is 3

使用transform:


分組變換(MIN)


回報如下:


0    1

1    1

2    1

3    1

4    1

5    1

6    1

7    1

8    1

Name: price, dtype: int64


pandas.core.series.Series # return type

RangeIndex(start=0, stop=9, step=1) # The returned Series' index

# length is 9    

兩個方法都返回一個Series對象,但是length第一個是3,而length第二個是9。


如果你想回答What is the minimum price paid by each customer,然后apply方法是比較適合選擇的方法。


如果你想回答What is the difference between the amount paid for each transaction vs the minimum payment,然后你想用transform,因為:


test['minimum'] = grouping.transform(min) # ceates an extra column filled with minimum payment

test.price - test.minimum # returns the difference for each row

Apply在這里工作并不僅僅是因為它返回一個3大小的系列,但是原始df的長度是9,您不能輕松地將它集成回原始df。


查看完整回答
反對 回復 2019-07-16
  • 3 回答
  • 0 關注
  • 559 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號