首页 > 解决方案 > 用 Pandas 将宽 df 融为长

问题描述

我正在从磁盘读取 csv - print(pd.read_csv('data.csv'))

    Unnamed:0    Company1    Company2    Company3 ...
0   2019-01-01   €100,000    €100,000    €100,000
1   2019-01-02   €100,000    €100,000    €100,000
2   2019-01-03   €100,000    €100,000    €100,000
3   2019-01-04   €100,000    €100,000    €100,000

正在读取的 CSV 是 df 上游的结果,并且未命名的日期列被索引。我的问题是我有 70 多家公司,因此有 70 多个专栏。当我将其写入表格时,我希望公司属于“company_name”列,然后“Company1”、“Company2”等的当前值属于“predicted”列。我会用 Spark 将这个最终的 df 写到一个表中。

这是我想要的格式:

date         company_name    predicted
2019-01-01   Company1        €100,000
2019-01-01   Company2        €100,000
2019-01-01   Company3        €100,000
2019-01-02   Company1        €100,000
2019-01-02   Company2        €100,000
2019-01-02   Company3        €100,000

我试过这个:

my_dict = pd.read_csv('data.csv')
df = pd.DataFrame(my_dict)
df.rename(columns={'Unnamed:0': 'date'}, inplace=True)
df = df.melt(id_vars=['date'], value_vars=df.columns[1:], var_name='company_name', 
value_name='predicted')
df.sort_values(by=['date'], inplace=True)
print(df)

这几乎可以工作,但日期列有NaN值:

        date   company_name   predicted
0       NaN    Company1       €100,000
1       NaN    Company1       €100,000
2       NaN    Company1       €100,000
3       NaN    Company1       €100,000
4       NaN    Company1       €100,000

标签: pythonpython-3.xpandas

解决方案


您可以像这样使用融化:

df.rename(columns={'Unnamed:0':'date'}, inplace=True) 
df.melt(col_level=0, id_vars='date').sort_values(by='date').reset_index(drop=True)                                                                                        

          date  variable     value
0   2019-01-01  Company1  €100,000
1   2019-01-01  Company2  €100,000
2   2019-01-01  Company3  €100,000
3   2019-01-02  Company1  €100,000
4   2019-01-02  Company2  €100,000
5   2019-01-02  Company3  €100,000
6   2019-01-03  Company1  €100,000
7   2019-01-03  Company2  €100,000
8   2019-01-03  Company3  €100,000
9   2019-01-04  Company1  €100,000
10  2019-01-04  Company2  €100,000
11  2019-01-04  Company3  €100,000

推荐阅读