如何在数据框中对包含字符串的一列进行透视?

6

我正在尝试重新塑造一个pandas数据框,通过将其中一列数据转换为行(通过透视或取消堆叠)。

我是新手,很可能我错过了一些显而易见的东西。我进行了广泛的搜索,但没有成功地应用任何我遇到的解决方案。

df
    Location    Month       Metric       Value
0   Texas       January     Temperature  10
1   New York    January     Temperature  20
2   California  January     Temperature  30
3   Alaska      January     Temperature  40
4   Texas       January     Color        Red
5   New York    January     Color        Blue
6   California  January     Color        Green
7   Alaska      January     Color        Yellow
8   Texas       February    Temperature  15
9   New York    February    Temperature  25
10  California  February    Temperature  35
11  Alaska      February    Temperature  NaN
12  Texas       February    Color        NaN
13  New York    February    Color        Purple
14  California  February    Color        Orange
15  Alaska      February    Color        Brown

我正在尝试将度量值“旋转”成列。最终目标是得到这样的结果:
Location    Month     Temperature   Color
Texas       January   10            Red
New York    January   20            Blue
California  January   30            Green
Alaska      January   40            Yellow
Texas       February  15    
New York    February  25            Purple
California  February  35            Orange
Alaska      February                Brown

我曾试过使用pivot、pivot_table以及unstack方法,但我确定我还缺少一些东西。许多复杂性似乎是因为我混合了字符串和数字,并且数据中还有一些缺失值。
到目前为止,这是我能够实现的最接近的结果,但我不想为月份列添加额外行,导致更多的空白值:
df.set_index(['Location','Month','Metric'], append=True, inplace=True)
df.unstack()

    Value
    Metric              Color   Temperature
    Location    Month       
0   Texas       January None    10
1   New York    January None    20
2   California  January None    30
3   Alaska      January None    40
4   Texas       January Red     None
5   New York    January Blue    None
6   California  January Green   None
7   Alaska      January Yellow  None

非常感谢您的帮助。这似乎是一个简单的问题,有很多可行的解决方案。

2个回答

5
您需要的是一个枢轴解决方案。输出结果符合您所需的语义-
Metric                Color Temperature
Location   Month                       
Alaska     February   Brown         NaN
           January   Yellow          40
California February  Orange          35
           January    Green          30
New York   February  Purple          25
           January     Blue          20
Texas      February     NaN          15
           January      Red          10

代码 -

df_p = df.pivot_table(index=['Location', 'Month'], columns=['Metric'], values='Value', aggfunc=np.sum)

非常感谢!对于我这个初学者来说,这似乎是最直接的解决方案。但是,与其他人建议使用unstack相比,是否存在任何缺点,我很感兴趣听听。此外,我添加了以下内容,以使输出格式符合我的要求: df_p.reset_index().rename_axis(None, axis=1) - brendxn

4

首先,正确排序需将列Month转换为有序分类,然后通过set_indexunstack进行重塑:

#add another months
cats = ['January','February']
df['Month'] = pd.Categorical(df['Month'], categories=cats, ordered=True)

如果月份已按原列顺序排列,感谢 @asongtoruin:

df['Month'] = pd.Categorical(df['Month'], categories=df['Month'].unique(), ordered=True)

df = (df.set_index(['Location','Month','Metric'])['Value']
       .unstack()
       .reset_index()
       .rename_axis(None, axis=1)
       .sort_values('Month'))
print (df)
     Location     Month   Color Temperature
0      Alaska   January  Yellow          40
2  California   January   Green          30
4    New York   January    Blue          20
6       Texas   January     Red          10
1      Alaska  February   Brown         NaN
3  California  February  Orange          35
5    New York  February  Purple          25
7       Texas  February     NaN          15

2
对于更高的灵活性,如何使用pd.Categorical(df['Month'], categories=df['Month'].unique(), ordered=True) - asongtoruin
@asongtoruin - 好主意,谢谢。 - jezrael
@asongtoruin,如果Month包含像这个问题中的字符串,那么它会对月份名称强制执行词典(字母)顺序,通常不是我们想要的。您需要手动编写正确的月份排序代码或者import calendar并使用calendar.month_name编辑: 算了,我错误地认为是pd.Categorical(df['month'].unique(), ordered=True) - Peter Leimbigler
@PeterLeimbigler 是的,你说得对 - 使用.unique()可以确保始终捕获到每个可用的月份,但不一定保留日历顺序。我猜这取决于OP认为什么更重要。 - asongtoruin
谢谢。对我来说,pivot_table方法似乎更简单。在这里使用unstack的优点是什么?还是只是个人喜好? - brendxn
@brendx - 我认为 pivot_table 只在需要聚合函数时使用。因此,更快、更好的方法是使用 set_index + unstack。如果有重复值,则最好使用 groupby + 聚合函数,这是 pivot_table 的更快替代方法。但这取决于你。祝你好运! - jezrael

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接