2017-08-16 167 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

相关问题