【问题标题】:Stack different column values into one column in a pandas dataframe将不同的列值堆叠到熊猫数据框中的一列中
【发布时间】:2021-06-07 11:16:30
【问题描述】:

我有以下数据框 -

df = pd.DataFrame({
    'ID': [1, 2, 2, 3, 3, 3, 4],
    'Prior': ['a', 'b', 'c', 'd', 'e', 'f', 'g'],
    'Current': ['a1', 'c', 'c1', 'e', 'f', 'f1', 'g1'],
    'Date': ['1/1/2019', '5/1/2019', '10/2/2019', '15/3/2019', '6/5/2019',
             '7/9/2019', '16/11/2019']
})

这是我想要的输出 -

desired_df = pd.DataFrame({
    'ID': [1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 4],
    'Prior_Current': ['a', 'a1', 'b', 'c', 'c1', 'd', 'e', 'f', 'f1', 'g',
                      'g1'],
    'Start_Date': ['', '1/1/2019', '', '5/1/2019', '10/2/2019', '', '15/3/2019',
                   '6/5/2019', '7/9/2019', '', '16/11/2019'],
    'End_Date': ['1/1/2019', '', '5/1/2019', '10/2/2019', '', '15/3/2019',
                 '6/5/2019', '7/9/2019', '', '16/11/2019', '']
})

我尝试了以下 -

keys = ['Prior', 'Current']
df2 = (
    pd.melt(df, id_vars='ID', value_vars=keys, value_name='Prior_Current')
        .merge(df[['ID', 'Date']], how='left', on='ID')
)
df2['Start_Date'] = np.where(df2['variable'] == 'Prior', df2['Date'], '')
df2['End_Date'] = np.where(df2['variable'] == 'Current', df2['Date'], '')
df2.sort_values(['ID'], ascending=True, inplace=True)

但这似乎不起作用。请帮忙。

【问题讨论】:

  • 代码格式化使用` 而不是'
  • 也请帮忙解决一下

标签: python pandas dataframe multiple-columns melt


【解决方案1】:

你可以使用stackpivot_table

k = df.set_index(['ID', 'Date']).stack().reset_index()
df = k.pivot_table(index = ['ID',0], columns = 'level_2', values = 'Date', aggfunc = ''.join, fill_value= '').reset_index()
df.columns = ['ID', 'prior-current', 'start-date', 'end-date']

输出:

    ID prior-current  start-date    end-date
0    1             a                1/1/2019
1    1            a1    1/1/2019            
2    2             b                5/1/2019
3    2             c    5/1/2019   10/2/2019
4    2            c1   10/2/2019            
5    3             d               15/3/2019
6    3             e   15/3/2019    6/5/2019
7    3             f    6/5/2019    7/9/2019
8    3            f1    7/9/2019            
9    4             g              16/11/2019
10   4            g1  16/11/2019            

说明:

stack / reset_index 之后,df 将如下所示:

   ID        Date  level_2   0
0    1    1/1/2019    Prior   a
1    1    1/1/2019  Current  a1
2    2    5/1/2019    Prior   b
3    2    5/1/2019  Current   c
4    2   10/2/2019    Prior   c
5    2   10/2/2019  Current  c1
6    3   15/3/2019    Prior   d
7    3   15/3/2019  Current   e
8    3    6/5/2019    Prior   e
9    3    6/5/2019  Current   f
10   3    7/9/2019    Prior   f
11   3    7/9/2019  Current  f1
12   4  16/11/2019    Prior   g
13   4  16/11/2019  Current  g1

现在,我们可以使用IDcolumn 0 作为索引/level_2 作为列/Date 列作为值。

最后,我们需要重命名列以获得所需的结果。

【讨论】:

    【解决方案2】:

    我的方法是逐步建立并达到目标df。第一步是使用melt()merge() 扩展您的代码。合并是根据“当前”和“之前”列完成的,以获取开始和结束日期。

    df = pd.DataFrame({
        'ID': [1, 2, 2, 3, 3, 3, 4],
        'Prior': ['a', 'b', 'c', 'd', 'e', 'f', 'g'],
        'Current': ['a1', 'c', 'c1', 'e', 'f', 'f1', 'g1'],
        'Date': ['1/1/2019', '5/1/2019', '10/2/2019', '15/3/2019', '6/5/2019',
                 '7/9/2019', '16/11/2019']
    })
    df2 = pd.melt(df, id_vars='ID', value_vars=['Prior', 'Current'], value_name='Prior_Current').drop('variable',1).drop_duplicates().sort_values('ID')
    df2 = df2.merge(df[['Current', 'Date']], how='left', left_on='Prior_Current', right_on='Current').drop('Current',1)
    df2 = df2.merge(df[['Prior', 'Date']], how='left', left_on='Prior_Current', right_on='Prior').drop('Prior',1)
    df2 = df2.fillna('').reset_index(drop=True)
    df2.columns = ['ID', 'Prior_Current', 'Start_Date', 'End_Date']
    

    另一种方法是定义一个自定义函数来获取日期,然后使用lambda函数:

    def get_date(x, col):
        try:
            return df['Date'][df[col]==x].values[0]
        except:
            return ''
    
    df2 = pd.melt(df, id_vars='ID', value_vars=['Prior', 'Current'], value_name='Prior_Current').drop('variable',1).drop_duplicates().sort_values('ID').reset_index(drop=True)
    df2['Start_Date'] = df2['Prior_Current'].apply(lambda x: get_date(x, 'Current'))
    df2['End_Date'] = df2['Prior_Current'].apply(lambda x: get_date(x, 'Prior'))
    

    输出

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-09-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-11-18
      相关资源
      最近更新 更多