【问题标题】:Create multiple rows by expanding data frame using Python通过使用 Python 扩展数据框创建多行
【发布时间】:2021-03-13 14:04:42
【问题描述】:

我正在尝试根据以下数据创建新的数据框,其中包含 4 列,start_year、end_ear、ego_id 和 alter_id。我需要使用 start_year 和 end_year 将数据转换为具有年度观察(年份列)的新数据框。例如,如果现有数据框中的start_year为2012年,end_year为2016年,则基于此行的新数据框应有5行,包括2012年、2013年、2014年、2015年和2016年。

d = {'start_year': [2012, 2016,2006], 'end_year': [2016, 2017,2016],'ego_id':['1011','1011','2211'],'alter_id':['3311','9192','1022']}
df = pd.DataFrame(data=d)
df

    start_year  end_year    ego_id  alter_id
0   2012    2016    1011    3311
1   2016    2017    1011    9192
2   2006    2016    2211    1022

执行此操作的一种简单方法可能是迭代原始数据框中的每一行,然后根据 start_year 和 end_year 创建新行,最后将这些行附加到新数据框中。

但是,我发现这种方法效率低下,因为我正在处理大型数据集。有没有办法更快?

df_empty=pd.DataFrame()
df_empty['year']=""

for i in range(df.shape[0]):
    row=df.iloc[i,]
    
    for yr in range(row.start_year,row.end_year+1):
        matched_row=pd.Series([],dtype=object)
        matched_row['year']=yr
        matched_row=pd.concat([matched_row,row[2:]],axis=0)
        df_empty=df_empty.append(matched_row,ignore_index=True)



df_empty

    year    alter_id    ego_id
0   2012    3311    1011
1   2013    3311    1011
2   2014    3311    1011
3   2015    3311    1011
4   2016    3311    1011
5   2016    9192    1011
6   2017    9192    1011
7   2006    1022    2211
8   2007    1022    2211
9   2008    1022    2211
10  2009    1022    2211
11  2010    1022    2211
12  2011    1022    2211
13  2012    1022    2211
14  2013    1022    2211
15  2014    1022    2211
16  2015    1022    2211
17  2016    1022    2211

【问题讨论】:

    标签: python pandas


    【解决方案1】:

    您可以使用列表推导来创建年份列表,然后 explode:

    print (df.assign(year=[list(range(lo, hi+1)) for lo, hi in df.filter(like="year").to_numpy()])
             .explode("year")
             .drop(["start_year", "end_year"], 1))
    
      ego_id alter_id  year
    0   1011     3311  2012
    0   1011     3311  2013
    0   1011     3311  2014
    0   1011     3311  2015
    0   1011     3311  2016
    1   1011     9192  2016
    1   1011     9192  2017
    2   2211     1022  2006
    2   2211     1022  2007
    2   2211     1022  2008
    2   2211     1022  2009
    2   2211     1022  2010
    2   2211     1022  2011
    2   2211     1022  2012
    2   2211     1022  2013
    2   2211     1022  2014
    2   2211     1022  2015
    2   2211     1022  2016
    

    【讨论】:

    • 这非常有效。我还有一栏要补充:duration_month 表示一年中自我与月改变之间的关系持续多长时间。有没有办法根据月份列爆炸? data = { "start_yr": [2012], "end_yr": [2014], "start_mon": [1], "end_mon": [7], "ego": ["1"], "alter": ["3"], } df = pandas.DataFrame(data=data)#desired outcome data = { "yr": [2012,2013,2014], "dur_mon": [12,12,7], "ego": ["1", "1","1"], "alter": ["3","3","3"], } df = pandas.DataFrame(data=data)
    【解决方案2】:

    这应该可行:

    import pandas
    
    # Your data
    data = {
        "start_year": [2012, 2016, 2006],
        "end_year": [2016, 2017, 2016],
        "ego_id": ["1011", "1011", "2211"],
        "alter_id": ["3311", "9192", "1022"],
    }
    df = pandas.DataFrame(data=data)
    
    # Add a column with all the years in between the start and end
    df["range"] = df.apply(lambda row: range(row["start_year"], row["end_year"] + 1), axis=1)
    
    # Create a new series that contains every year on a new line, maintaining the original index
    years = df.apply(lambda x: pandas.Series(x["range"]), axis=1).stack().reset_index(level=1, drop=True)
    years.name = "year"
    
    # Join back to the original dataframe on the index
    df = df.drop(columns=["range"]).join(years.astype(int))
    df
    

    【讨论】:

      猜你喜欢
      • 2019-05-12
      • 1970-01-01
      • 2020-10-11
      • 2017-10-17
      • 1970-01-01
      • 2021-02-01
      • 1970-01-01
      • 2021-09-16
      • 2019-02-27
      相关资源
      最近更新 更多