2017-06-19 27 views
0

的Python:比較字符串我有以下的數據幀整個下一列

df1: 
     2000 2001 2002 
     a a  a 
     b b  c 
     c c  d 

所以,在2002年的價值B獲得了C代替。我現在想要的是針對每一列,檢查列的每個值(即分別針對a,b和c)是否是下一列的成員。然後,我想爲a,b,c和d輸出一個指示字符串成爲第一個成員的日期以及它停止成爲成員的日期。像這樣:

df2: 
     a  b  c  d 
     2000 2000 2000 2002 
     NaN 2002 Nan NaN 

任何人都可以幫助我如何在Python中實現這個嗎?

編輯:這是我將如何開始,但我不知道如何在python中實現它。

​​

從理論上講,這應該給我一個數據幀,只顯示刪除值的日期。例如:

df2: 
    2002 
    b 

然後,我會做一個類似的分析,但對於添加的值,然後合併兩個數據框。但是,我不知道如何將每列精確轉換爲列表,並檢查v是否是該列表的一部分,然後轉到下一列。

+0

您有解決方案的嘗試嗎? – EFT

+0

這是作業嗎?不知道我是否應該爲你寫一個算法。 –

+1

不,這不是作業。我在 –

回答

1

來看看這裏的一個有用的工具是pd.DataFrame().stack()

df1.stack() 
Out[24]: 
0 2000 a 
    2001 a 
    2002 a 
1 2000 b 
    2001 b 
    2002 c 
2 2000 c 
    2001 c 
    2002 d 
dtype: object 

因爲列名排序很好,你可以排序這個,然後使用drop_duplicates()獲得:

df1.stack().sort_index(level=1).drop_duplicates() 
Out[26]: 
0 2000 a 
1 2000 b 
2 2000 c 
    2002 d 
dtype: object 

df1.stack().sort_index(level=1).drop_duplicates(keep='last') 
Out[28]: 
1 2001 b 
0 2002 a 
1 2002 c 
2 2002 d 
dtype: object 

要轉換這些逐年給予年由價值指數,而不是值,你可以添加.reset_index().set_index(0)['level_1']到以下任一:

start = df1.stack().sort_index(level=1).drop_duplicates().reset_index().set_index(0)['level_1'] 
start 
Out[31]: 
0 
a 2000 
b 2000 
c 2000 
d 2002 
Name: level_1, dtype: object 

也這樣對其他之後,將其稱爲end,則可以在由列構造的字典上使用pd.Series().map(),以獲取第一個值不出現的名稱,而不是最後一個字段的名稱。

cols = df1.columns.tolist()+[np.nan] 
next_col = {cols[i]:cols[i+1] for i in range(len(cols)-1)} 
end = end.map(next_col) 
end 
Out[36]: 
0 
b 2002 
a  NaN 
c  NaN 
d  NaN 
Name: level_1, dtype: object 

爲了然後結合這些創造df2,您可以使用pd.concat

df2 = pd.concat([start, end], axis=1).T.reset_index(drop=True) 

df2 
Out[40]: 
     a  b  c  d 
0 2000 2000 2000 2002 
1 NaN 2002 NaN NaN 
+0

之上加了一個嘗試哇。這個工作真的很棒,但只有開始值,即在df2中有0索引。結束值始終是下一列。例如,我得到以下結果a:2000,2001 b:2000 2001,c:2000,2001 .... 我說得對,我只是做了相同的程序結束作爲開始?因爲在運行'start = df1.stack()。sort_index(level = 1).drop_duplicates().setup_index().set_index(0)['level_1']'我執行'end = start'並執行其餘部分。 –

+0

錯誤可能是'next_col = {cols [i]:cols [i + 1] for i in range(len(cols)-1)}'cols [I + 1]只引用下一個單元格。我可能需要一個[最後一列]命令嗎? –

+0

'end'與'start'幾乎相同,只是在排序後保留最後一個副本而不是第一個。這就是''end'中的'.drop_duplicates(keep ='last')'中的'keep ='last''參數的意思。通過將'ascending = False'傳遞給'.sort_index()'作爲'end',你可以得到類似的結果,儘管我認爲最好給出選擇來存儲排序的堆棧數據幀作爲中間步驟。 'nextcol'應該只指向下一個單元格 - 否則,即使使用'keep ='last'','end'也會將最後一列顯示出來,而不是第一列不再顯示。 – EFT

0

將每列解析爲一個列表,然後從那裏開始。

input = ''' 2000 2001 2002 
     a a  a 
     b b  c 
     c c  d ''' 

lines = [] 
for line in input.split('\n'): 
    print ' '.join(line.split()) 
    lines.append(line.split()) 

print lines 

輸出:

[['2000', '2001', '2002'], ['a', 'a', 'a'], ['b', 'b', 'c'], ['c', 'c', 'd']] 
1

一般算法:通過一年

1)組數據到列表中。 lzts = [['2000', 'a', 'b', 'c'], ['2001', 'a', 'b', 'c'], etc]

2)創建函數以遍歷列表,搜索給定值的實例。

def search(val): 
    ans = (float('NaN'), float('NaN')) #start & end date for given value 
    for lzt in lzts: 
    if val in lzt[1:]: #skip first value since its the year 
     if math.isnan(ans[0]): #no start date yet 
     ans[0] = lzt[0] #add the year 
    else: #value not found 
     if not math.isnan(ans[0]): #already has start date 
     ans[1] = lzt[0] #add the year as end date 

注意:此解決方案假設一旦值停止出現一年,它將永遠消失。如果某個值未出現一年後再返回,則結果將不準確。