2017-08-16 172 views
1

我有一個CSV文件,我讀入一個Pandas DataFrame,其中包含以分號分隔的多個年份值的列。從Pandas DataFrame中的字符串中提取最小和最大年份

我需要從字符串中提取最小值和最大值,並將每個值保存在一個新列中。

我能夠打印最小值和最大值,但我似乎無法從保存到新列中的每一行中獲取正確的值。

任何幫助,非常感謝。

樣品數據框:

import pandas as pd 
import numpy as np 

raw_data = {'id': ['1473-2262', '2327-9214', '1949-8349', '2375-6314', 
        '0095-6562'], 
      'years': ['2000; 2001; 2002; 2003; 2004; 2004; 2004; 2005', 
         '2003; 2004; 2005', '2015', np.nan, '2012; 2014']} 
df = pd.DataFrame(raw_data, columns = ['id', 'years']) 

這是數據幀,我需要:

  id           years minyear maxyear 
0 1473-2262 2000; 2001; 2002; 2003; 2004; 2004; 2004; 2005 2000.0 2005.0 
1 2327-9214        2003; 2004; 2005 2003.0 2005.0 
2 1949-8349           2015 2015.0 2015.0 
3 2375-6314            NaN  NaN  NaN 
4 0095-6562          2012; 2014 2012.0 2014.0 

我可以打印的最小和最大:

x = df['years'].notnull() 

for row in df['years'][x].str.split(pat=';'): 
    lst = list() 
    for item in row: 
     lst.append(int(item)) 
    print('Min=',min(lst),'Max=',max(lst)) 

Min= 2000 Max= 2005 
Min= 2003 Max= 2005 
Min= 2015 Max= 2015 
Min= 2012 Max= 2014 

下面是我試過將這些值捕獲到新列中:

x = df['years'].notnull() 

for row in df['years'][x].str.split(pat=';'): 
    lst = list() 
    for item in row: 
     lst.append(int(item)) 
    df['minyear']=min(lst) 
    df['maxyear']=max(lst) 

只有最後一行的值纔會保存到新列中。

   id           years minyear maxyear 
0 1473-2262 2000; 2001; 2002; 2003; 2004; 2004; 2004; 2005  2012  2014 
1 2327-9214        2003; 2004; 2005  2012  2014 
2 1949-8349           2015  2012  2014 
3 2375-6314            NaN  2012  2014 
4 0095-6562          2012; 2014  2012  2014 

回答

2

我認爲你需要str.splitexpand=TrueDataFrame,然後轉換爲float

指數值是相同的,所以分配新列:

df1 = df['years'].str.split('; ', expand=True).astype(float) 
df = df.assign(maxyear=df1.max(axis=1),minyear=df1.min(axis=1)) 
#same as 
#df['maxyear'], df['minyear'] = df1.min(axis=1), df1.max(axis=1) 
print (df) 
      id           years maxyear minyear 
0 1473-2262 2000; 2001; 2002; 2003; 2004; 2004; 2004; 2005 2000.0 2005.0 
1 2327-9214        2003; 2004; 2005 2003.0 2005.0 
2 1949-8349           2015 2015.0 2015.0 
3 2375-6314            NaN  NaN  NaN 
4 0095-6562          2012; 2014 2012.0 2014.0 
0

一個類似於jezrael提出的一個解決方案,但使用轉換成系列。 警告:此解決方案不能很好地擴展。

years = df.years.str.split(";").apply(pd.Series).astype(float)   
#0  1  2  3  4  5  6  7 
#0 2000.0 2001.0 2002.0 2003.0 2004.0 2004.0 2004.0 2005.0 
#1 2003.0 2004.0 2005.0  NaN  NaN  NaN  NaN  NaN 
#2 2015.0  NaN  NaN  NaN  NaN  NaN  NaN  NaN 
#3  NaN  NaN  NaN  NaN  NaN  NaN  NaN  NaN 
#4 2012.0 2014.0  NaN  NaN  NaN  NaN  NaN  NaN 
df['maxyear'], df['minyear'] = years.min(axis=1), years.max(axis=1) 
+0

我的解決方案只有你的兩倍慢。不是太糟糕:) – DyZ

+0

不,只是5.它不會隨着行數線性縮放嗎? – DyZ

+0

@jezrael你是對的。我想知道爲什麼。 – DyZ

相關問題