从Pandas DataFrame中的字符串中提取最小和最大年份

时间:2017-08-16 17:53:06

标签: python pandas

我有一个CSV文件,我读入Pandas DataFrame,其中包含一个以分号分隔的多年值的列。

我需要从字符串中提取最小值和最大值,并将每个值保存在新列中。

我可以打印最小值和最大值,但我似乎无法从保存到新列的每一行中获取正确的值。

非常感谢任何帮助。

示例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'])

这是我需要的DataFrame:

          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 个答案:

答案 0 :(得分:2)

我认为您需要str.split expand=True用于新DataFrame,然后转为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

答案 1 :(得分: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)