2016-07-01 57 views
3

我正在處理包含數據框元素內數組的熊貓數據框。我試圖「應用」這些元素的功能,然後返回一個數組。但是我有一些非常不一致的行爲。該功能在前幾次運行良好,但後來失敗。這裏是我的代碼:對熊貓數據框元素中的數組使用'apply'

import pandas as pd 
import numpy as np 

def g(x): # Function fails if I omit the .tolist() 
    return (np.concatenate([x['B'][1:], x['C'][1:]])).tolist() 

df = pd.DataFrame({'A' : (1,2,3), \ 
        'B': (np.array([0,1,2,3]),np.array([3,4,5,6]),np.array([6,7,8,9])), \ 
        'C': (np.array([0,1,2,3]),np.array([2,9,6,9]),np.array([2,4,6,7]))}) 
# Before we start 
print(df) 
print("B is type: ", type(df.loc[0,'B'])) 
# First time 
df['G'] = df.apply(g, axis=1) 
print("G is type: ", type(df.loc[0,'G'])) 
# Second time 
df['H'] = df.apply(g, axis=1) 
print("H is type: ", type(df.loc[0,'H'])) 
# Third time 
df['I'] = df.apply(g, axis=1) 
print("I is type: ", type(df.loc[0,'I'])) 
# Fourth time - this one fails for me 
df['J'] = df.apply(g, axis=1) 
print("J is type: ", type(df.loc[0,'J'])) 
# Fifth time 
df['K'] = df.apply(g, axis=1) 
print("K is type: ", type(df.loc[0,'K'])) 

該代碼運行良好,直到行df ['J'],它在哪裏失敗。輸出是這樣的:

A    B    C 
0 1 [0, 1, 2, 3] [0, 1, 2, 3] 
1 2 [3, 4, 5, 6] [2, 9, 6, 9] 
2 3 [6, 7, 8, 9] [2, 4, 6, 7] 
B is type: <class 'numpy.ndarray'> 
G is type: <class 'list'> 
H is type: <class 'list'> 
I is type: <class 'list'> 

再有就是與"ValueError: Wrong number of items passed 6, placement implies 1"完成一個很長的錯誤消息,並且也有一個"KeyError: 'J'"在那裏了。

瘋狂的事情是,功能運行良好的前幾次。我的問題是:

  • 爲什麼我的代碼在df['J']失敗?
  • 我怎麼能得到g(x)返回一個numpy數組而不是一個列表?如果我忽略了.tolist(),它會給我一個錯誤。
  • 有沒有一種更簡單的方法來處理數組中的數組?

任何幫助將巨大讚賞!我花了2天時間試圖瞭解這裏發生了什麼。

P.S.我沒有解釋爲什麼我在數據框元素中使用數組,但是我可以解釋你是否認爲它會有幫助。

+1

你的代碼在'J'失敗的原因是因爲一旦你得到6列,熊貓適合現有列的'g'(長度爲6)的結果。然後它返回一個有6列的數據框,它不適合'J'列。在將其分配給'J'之前,嘗試'df.apply(g,axis = 1)'。 – IanS

+1

@IanS感謝您的解釋,我也在爲此付出努力。大熊貓這次只是認爲它是一個數據框,而不是以前的?看起來之前,它提供了一個'Series',但突然它變成了一個'DataFrame'。 – ysearka

+1

@ysearka我也一直在努力,我沒有一個確切的解釋。我猜大熊貓根據結果的維數作出猜測,但我不知道如何強迫它做其他事情。 – IanS

回答

2

在您應用g函數的不同時間之間,您的數據框會發生變化,那麼熊貓的反應將不會每次都是相同的。如果你只需要將其應用到列BC,我建議你鍵入:

df['J'] = df[['B','C']].apply(g, axis=1) 
print("J is type: ", type(df.loc[0,'J'])) 

這樣它工作正常(但再次只取列BC考慮在內)。

至於錯誤,根據Ians,這是因爲只要apply的輸出超過6列,就會變成DataFrame而不是Series。然後它不能設置爲df['J']

+0

非常感謝您的回答!我嘗試了你的第一個建議,只通過'B'和'C'來應用,就像這樣:'df ['J'] = df [['B','C']]。apply(g,axis = 1)'。它的工作!我認爲這是因爲@IanS給出的原因:返回的系列中的元素數量不再與數據框中的列數相匹配。不過,您的其他建議在編輯中並不適用於我。不知道爲什麼。另外,關於關鍵錯誤,我不認爲原因是'df.loc [0,'J']',因爲我認爲執行已經在此行運行之前終止。 – Michael

+0

@Michael好的感謝您的反饋,我清理我的答案。 – ysearka

+0

l @ ysearka,我暫時不打算提問,因爲我仍然希望有人能夠提供一種通用的解決方案,無論列數是多少,但感謝您的幫助。 – Michael