从字典创建DataFrame和索引顺序问题?

3
我是使用带有Python 3.7.1和pandas 0.23.4的最新版Anaconda。 pandas文档中写道:
当数据是字典时,如果没有传递索引,则Series索引将按照字典的插入顺序排序。
我使用一个没有传递索引的字典来实例化pandas DataFrame。
newspapers = {'Jim':{'Mon':15,'Tue':17,'Wed':21,'Thu':16,'Fri':19},\
     'Tony':{'Mon':8,'Tue':15,'Wed':11,'Thu':16,'Fri':13}, \
     'Colin':{'Mon':13,'Tue':17,'Wed':19,'Thu':17,'Fri':20} \
    }
newspapers_df = pd.DataFrame(newspapers)

为什么这个不按照插入顺序显示,星期一、星期二、星期三、星期四、星期五?
print(newspapers_df)

输出:

      Jim  Tony  Colin
Fri   19    13     20
Mon   15     8     13
Thu   16    16     17
Tue   17    15     17
Wed   21    11     19

1
你使用的pandas版本是多少?因为这种行为是在特定版本中引入的。 - EdChum
你应该在 github 上报告错误,因为那里更合适。 - EdChum
v0.23.4的更新帖。我不确定是否发现了一个错误,我认为可能是我漏掉了什么。 - boardtc
1
这对我来说看起来像是一个bug,我会发布一个问题,因为它应该可以工作。 - EdChum
提出问题 #25911 @edChum,谢谢,你能把你的评论转化成答案吗? - boardtc
1
说实话,我认为我不需要这样做。对我来说,这是一个错误,有很多解决方法,但真正的问题是为什么它不起作用。 - EdChum
3个回答

2

对我来说,它似乎是个错误。在使用Python 3.5和Pandas 0.24.2时,可以在字典推导中创建Series并将其传递给DataFrame构造函数:

最初的回答:

newspapers_df = pd.DataFrame({k:pd.Series(v) for k, v in newspapers.items()})

print (newspapers_df)
     Jim  Tony  Colin
Mon   15     8     13
Tue   17    15     17
Wed   21    11     19
Thu   16    16     17
Fri   19    13     20

你的数据可能有以下解决方案 - 使用DataFrame.reindex或使用有序CategoricalIndex:
newspapers_df = pd.DataFrame(newspapers)

L = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri']
newspapers_df = newspapers_df.reindex(L)

或者:

newspapers_df.index = pd.CategoricalIndex(newspapers_df.index, ordered=True, categories=L)
newspapers_df = newspapers_df.sort_index()
print (newspapers_df)
     Jim  Tony  Colin
Mon   15     8     13
Tue   17    15     17
Wed   21    11     19
Thu   16    16     17
Fri   19    13     20

是的,排序并传递索引可以正常工作,谢谢。但这不是问题的关键。 - boardtc
1
@boardtc - 是的,那么第一段有效吗?我认为只有外部字典被正确处理了,深层次的没有。 - jezrael
你的第一段中的newspapers_df打印出来的结果和你展示给我的一样。我可以在pandas-dev的github上报告一个bug。 - boardtc
https://github.com/pandas-dev/pandas/issues/25911 已经开启,但社区不希望修复。 - boardtc

2
可以使用numpy.argsort()进行相同的排序:
days_dict = {'Mon':0, 'Tue':1,'Wed':2,'Thu':3,'Fri':4,'Sat':5,'Sun':6}
df = pd.DataFrame(newspapers).reset_index()
df.iloc[np.argsort(df['index'].map(days_dict)),:]

0

看起来pd.Series和pd.DataFrame处理方式不同。

我有类似的Python环境,结果可以在我的电脑上复制。此外,Jezrel的pd.Series案例也可以在我的电脑上复制。

我查阅了手册,并发现两个结果都遵循文档。

对于Series,关键是索引。当数据是字典且未传递索引时,Series索引按照字典插入顺序排序,如果您使用的是Python版本>=3.6和Pandas版本>=0.23。

对于DataFrame:关键是列。如果未传递轴标签,则它们将基于常识规则从输入数据构建。

注意:当数据是字典且未指定列时,DataFrame列按照字典插入顺序排序,如果您使用的是Python版本>=3.6和Pandas版本>=0.23。

这意味着,如果您想确保列和索引都排序,您可能需要传递索引或稍后对它们进行排序。

希望这回答了您的问题。


答案是pandas中存在一个bug! - boardtc

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