我认为你需要执行的操作——将表格转换为非透视形式——被称为“melting”(也叫“长格式化”)。在这种情况下,通过使用pd.melt
函数可以完成大部分难点,其余即为重命名和重新排列:
df = pd.DataFrame(sample).reset_index().rename(columns={"index": "item"})
df = pd.melt(df, "item", var_name="user").dropna()
df = df[["user", "item", "value"]].reset_index(drop=True)
仅仅调用DataFrame
会生成我们想要的信息,但是形状不正确:
>>> df = pd.DataFrame(sample)
>>> df
user1 user2 user3
item1 2.5 2.5 NaN
item2 3.5 3.0 4.5
item3 3.0 3.5 NaN
item4 3.5 4.0 NaN
item5 2.5 NaN 1.0
item6 3.0 NaN 4.0
那么我们将索引提升为一个真正的列,并改进名称:
>>> df = pd.DataFrame(sample).reset_index().rename(columns={"index": "item"})
>>> df
item user1 user2 user3
0 item1 2.5 2.5 NaN
1 item2 3.5 3.0 4.5
2 item3 3.0 3.5 NaN
3 item4 3.5 4.0 NaN
4 item5 2.5 NaN 1.0
5 item6 3.0 NaN 4.0
然后我们可以调用 pd.melt
来转换列。如果我们没有指定我们想要的变量名 "user",它就会给它一个无聊的名称 "variable"(就像它给数据本身起的无聊名称 "value" 一样)。
>>> df = pd.melt(df, "item", var_name="user").dropna()
>>> df
item user value
0 item1 user1 2.5
1 item2 user1 3.5
2 item3 user1 3.0
3 item4 user1 3.5
4 item5 user1 2.5
5 item6 user1 3.0
6 item1 user2 2.5
7 item2 user2 3.0
8 item3 user2 3.5
9 item4 user2 4.0
13 item2 user3 4.5
16 item5 user3 1.0
17 item6 user3 4.0
最后,我们可以重新排列和重新编号索引:
>>> df = df[["user", "item", "value"]].reset_index(drop=True)
>>> df
user item value
0 user1 item1 2.5
1 user1 item2 3.5
2 user1 item3 3.0
3 user1 item4 3.5
4 user1 item5 2.5
5 user1 item6 3.0
6 user2 item1 2.5
7 user2 item2 3.0
8 user2 item3 3.5
9 user2 item4 4.0
10 user3 item2 4.5
11 user3 item5 1.0
12 user3 item6 4.0
melt
很实用,一旦你习惯了它。通常,在这里,你需要在操作前后进行一些重命名/重新排序。
from collections import defaultdict; d = defaultdict(dict); for user, item, value in df.values: d.setdefault(user, {})[item] = value
。 - falsetru.to_dict()
,可以使用df.to_dict()
。 - danodonovan