使用 Pandas 将列转换为行
Posted
技术标签:
【中文标题】使用 Pandas 将列转换为行【英文标题】:Convert columns into rows with Pandas 【发布时间】:2022-01-08 17:37:06 【问题描述】:所以我的数据集有 n 个日期的位置信息。问题是每个日期实际上是不同的列标题。例如 CSV 看起来像
location name Jan-2010 Feb-2010 March-2010
A "test" 12 20 30
B "foo" 18 20 25
我希望它看起来像
location name Date Value
A "test" Jan-2010 12
A "test" Feb-2010 20
A "test" March-2010 30
B "foo" Jan-2010 18
B "foo" Feb-2010 20
B "foo" March-2010 25
我的问题是我不知道该列中有多少个日期(尽管我知道它们总是以名称开头)
【问题讨论】:
***.com/questions/19842066/… 【参考方案1】:更新
从 v0.20 开始,melt
是一阶函数,现在可以使用
df.melt(id_vars=["location", "name"],
var_name="Date",
value_name="Value")
location name Date Value
0 A "test" Jan-2010 12
1 B "foo" Jan-2010 18
2 A "test" Feb-2010 20
3 B "foo" Feb-2010 20
4 A "test" March-2010 30
5 B "foo" March-2010 25
旧(ER)版本:
您可以使用pd.melt
获取大部分路径,然后进行排序:
>>> df
location name Jan-2010 Feb-2010 March-2010
0 A test 12 20 30
1 B foo 18 20 25
>>> df2 = pd.melt(df, id_vars=["location", "name"],
var_name="Date", value_name="Value")
>>> df2
location name Date Value
0 A test Jan-2010 12
1 B foo Jan-2010 18
2 A test Feb-2010 20
3 B foo Feb-2010 20
4 A test March-2010 30
5 B foo March-2010 25
>>> df2 = df2.sort(["location", "name"])
>>> df2
location name Date Value
0 A test Jan-2010 12
2 A test Feb-2010 20
4 A test March-2010 30
1 B foo Jan-2010 18
3 B foo Feb-2010 20
5 B foo March-2010 25
(可能想输入.reset_index(drop=True)
,只是为了保持输出干净。)
注意:pd.DataFrame.sort
has been deprecated支持pd.DataFrame.sort_values
。
【讨论】:
@DSM 这个函数的反函数是什么。即如何将df2
[返回] 转换为df
@3kstc 试试here 或here。你想研究枢轴。可能是pandas.pivot_table(df2,values='Value',index=['location','name'],columns='Date').reset_index()
。
@DSM 有没有办法倒退?这意味着我有很多同名的行,我希望所有日期都在不同的列上
@Adrian 您可以在 df 操作上取消熔化/反向熔化(也称为旋转)。有关更多详细信息,请查看此***.com/questions/28337117/…【参考方案2】:
将set_index
与stack
一起用于MultiIndex Series
,然后为DataFrame
添加reset_index
与rename
:
df1 = (df.set_index(["location", "name"])
.stack()
.reset_index(name='Value')
.rename(columns='level_2':'Date'))
print (df1)
location name Date Value
0 A test Jan-2010 12
1 A test Feb-2010 20
2 A test March-2010 30
3 B foo Jan-2010 18
4 B foo Feb-2010 20
5 B foo March-2010 25
【讨论】:
【参考方案3】:我想我找到了一个更简单的解决方案
temp1 = pd.melt(df1, id_vars=["location"], var_name='Date', value_name='Value')
temp2 = pd.melt(df1, id_vars=["name"], var_name='Date', value_name='Value')
连接整个temp1
与temp2
的列name
temp1['new_column'] = temp2['name']
你现在得到了你想要的。
【讨论】:
【参考方案4】:pd.wide_to_long
您可以在年份列中添加前缀,然后直接提供给pd.wide_to_long
。我不会假装这是高效,但在某些情况下它可能比pd.melt
更方便,例如当您的列已经有适当的前缀时。
df.columns = np.hstack((df.columns[:2], df.columns[2:].map(lambda x: f'Valuex')))
res = pd.wide_to_long(df, stubnames=['Value'], i='name', j='Date').reset_index()\
.sort_values(['location', 'name'])
print(res)
name Date location Value
0 test Jan-2010 A 12
2 test Feb-2010 A 20
4 test March-2010 A 30
1 foo Jan-2010 B 18
3 foo Feb-2010 B 20
5 foo March-2010 B 25
【讨论】:
【参考方案5】:添加一个可以复制的笔记本的链接,使用pandas.melt
演示@DMS 的答案:
df.melt(id_vars=["location", "name"],
var_name="date",
value_name="value")
https://deepnote.com/@DataScience/Unpivot-a-DataFrame-from-wide-to-long-format-lN7WlqOdSlqroI_7DGAkoA
【讨论】:
以上是关于使用 Pandas 将列转换为行的主要内容,如果未能解决你的问题,请参考以下文章