bounty将在3天后过期。回答此问题可获得+200声望奖励。freebie希望吸引更多人关注此问题。
我在尝试编写可理解的pandas
时遇到了麻烦,这让我觉得我缺少了一些特性或用法(可能是pd.melt
方法)。
我想合并两个数据集,它们都很相似:
time
,表示状态变更的时间name
和instance
是用于唯一地标识事物的记录条目的复合标识。- 最后是一个值,它是为那个事物在那个时间改变的状态命名的。
因此,我想合并的每个数据集中的示例记录如下:
dict(time=0, name="a", instance=0, state=1)
dict(time=5, name="a", instance=0, location="london")
我想将这两个记录集合并为一个记录集,其中每个(name, instance)
在每个时间都有最后一个已知的state
和location
。
[
dict(time=0, name="a", instance=0, state=1, location=np.nan),
dict(time=5, name="a", instance=0, state=1, location="london"),
]
为了达到这个目的,我目前做了pd.DataFrame.pivot_table
,pd.DataFrame.ffill
,pd.DataFrame.melt
和pd.DataFrame.reset_index
的组合。它似乎按预期工作,但感觉非常麻烦/不可读,特别是当我开始使用pd.DataFrame.melt
时。
我觉得我遗漏了pd.DataFrame.melt
函数的一些用法,但我不确定如何将文档应用于我正在使用的具有pd.MultiIndex
列的数据集,或者我是否遗漏了我应该使用的其他pandas
实用程序。
如果发现melt
不是我应该使用的,我会用更合适的内容更新问题标题。
这是我的资料
import pandas as pd
states = [
dict(time=0, name="a", instance=0, state=0),
dict(time=0, name="a", instance=1, state=0),
dict(time=0, name="a", instance=2, state=0),
dict(time=0, name="b", instance=1, state=0),
dict(time=0, name="b", instance=2, state=0),
dict(time=1, name="a", instance=1, state=1),
dict(time=2, name="a", instance=2, state=1),
dict(time=2, name="b", instance=1, state=1),
]
locations = [
dict(time=0, name="a", instance=0, location="tokyo"),
dict(time=0, name="a", instance=1, location="tokyo"),
dict(time=0, name="a", instance=2, location="tokyo"),
dict(time=0, name="b", instance=1, location="tokyo"),
dict(time=0, name="b", instance=2, location="tokyo"),
dict(time=1, name="a", instance=0, location="london"),
dict(time=1, name="a", instance=2, location="london"),
dict(time=1, name="b", instance=1, location="london"),
dict(time=1, name="b", instance=2, location="london"),
dict(time=1, name="a", instance=1, location="paris"),
dict(time=2, name="a", instance=2, location="paris"),
dict(time=2, name="b", instance=1, location="paris"),
]
states = pd.DataFrame.from_dict(states)
locations = pd.DataFrame.from_dict(locations)
combined = pd.concat([states, locations], axis="index")
combined = combined.pivot_table(
index="time",
columns=["name", "instance"],
values=["state", "location"],
aggfunc="last",
)
combined = combined.ffill()
ugly_melt = combined.melt(ignore_index=False)
ugly_melt = ugly_melt.rename(columns={None: "state_status"})
ugly_melt = (
ugly_melt.reset_index()
.pivot(
index=["time", "name", "instance"],
columns=["state_status"],
values="value",
)
.reset_index()
)
print(ugly_melt)
3条答案
按热度按时间lxkprmvk1#
请注意,
combined
在ffill
之后看起来是这样的。有两列,
location
和state
。您可以分别对它们执行melt
操作,然后再对它们执行merge
操作。roejwanj2#
数据集:
看起来时间、名称和示例是用于索引数据的级别,使用
set_index
将它们添加到索引中是有意义的:一旦MultiIndex就绪,您就可以沿着数据行串连状态和位置。这会在状态数据行中留下一些NaN。请先排序索引,让项目先依时间排列,然后根据相同的名称和执行严修将数据分组,最后执行向前填满。
结果和你的略有不同。我得到的是:
您将获得:
首先,我得到了一个MultiIndex DataFrame。如果您不喜欢它,可以使用
reset_index()
。(时间、名称、示例)=(2,a,0)。没有一个输入数据具有这种值的组合,所以这就是为什么它没有出现在我的结果中。它出现在你的结果中是因为pivot_table
的工作方式。这可能是一个可取的行为,也可能不是,由你来决定。watbbzwu3#
您可以简单地对两个数据集进行连接和过滤,记住
time
约束(只能对先前/当前状态进行连接,而不能对未来状态进行连接)。这消除了执行正向填充
ffill()
的需要,并且使用连接和过滤器比pd.melt
方法更容易理解。初始化代码
实施
这将产生以下
merged_df
结果的长度来自
location
数据,如果你想让每个名称-示例-位置都有一个时间,你可以事先做一个外部连接。