在加入多个数据帧时保留原始分类映射
Preserve Original Categorical Mappings while Joining Multiple Dataframes
我有 n
个数据框,每个数据框有一列,数据类型为 category
。不同帧的列有部分重叠。我想在将列加入新框架时共享列之间的类别 -> ID 映射:
In [362]: af = pd.DataFrame(pd.Series(['a1','a2', 'b1'], dtype="category", name='a'))
In [365]: bf = pd.DataFrame(pd.Series(['b1','b2', 'a1'], dtype="category", name='b'))
In [373]: all_categories = pd.Categorical(['a1','a2','b1','b2'])
In [376]: show_mapping(af.a)
[('a1', 0), ('a2', 1), ('b1', 2)]
In [377]: af.a.cat = all_categories
In [378]: show_mapping(af.a)
[('a1', 0), ('a2', 1), ('b1', 2), ('b2', 3)]
In [379]: show_mapping(bf.b)
[('b2', 0), ('a1', 1), ('b1', 2)]
In [380]: bf.b.cat = all_categories
In [381]: show_mapping(bf.b)
[('a1', 0), ('a2', 1), ('b1', 2), ('b2', 3)]
现在我将这些帧与我假设现在相同的映射连接起来:
In [382]: df = af.join(bf)
但是当我打印列的映射时,它们会重置:
In [384]: show_mapping(df.a)
[('a1', 0), ('a2', 1), ('b1', 2)]
In [385]: show_mapping(df.b)
[('b2', 0), ('a1', 1), ('b1', 2)]
为什么在加入框架后会自动重做映射,我怎样才能达到我的预期?
def show_mapping(x):
print(list(sorted(zip(x.cat.categories, x.cat.codes), key=lambda x : x[1])))
编辑
所有的困惑都来自于使用了糟糕的展示功能。下面的 show 函数实际上工作正常。将其与 set_categories
方法而不是 .cat = ...
方法结合使用,结果一切正常:
def show_mapping(s):
print([(e, s.cat.codes[i]) for i, e in enumerate(s)])
您可以通过 all_categories
使用 set_categories
在每个分类列中使用相同的类别,因此在 join
之后得到相同的代码:
af = pd.DataFrame(pd.Series(['a1','a2', 'b1'], dtype="category", name='a'))
bf = pd.DataFrame(pd.Series(['b1','b2', 'a1'], dtype="category", name='b'))
def show_mapping(x):
return (list(sorted(zip(x.cat.categories, x.cat.codes), key=lambda x : x[1])))
print(af.a)
0 a1
1 a2
2 b1
Name: a, dtype: category
Categories (3, object): [a1, a2, b1]
all_categories = pd.Categorical(['a1','a2','b1','b2'])
af.a = af.a.cat.set_categories(all_categories)
bf.b = bf.b.cat.set_categories(all_categories)
已添加类别b2
:
print(af.a)
0 a1
1 a2
2 b1
Name: a, dtype: category
Categories (4, object): [a1, a2, b1, b2]
print(show_mapping(af.a))
[('a1', 0), ('a2', 1), ('b1', 2)]
print(show_mapping(bf.b))
[('b1', 0), ('a1', 2), ('a2', 3)]
df = af.join(bf)
print(show_mapping(df.a))
[('a1', 0), ('a2', 1), ('b1', 2)]
print(show_mapping(df.b))
[('b1', 0), ('a1', 2), ('a2', 3)]
我有 n
个数据框,每个数据框有一列,数据类型为 category
。不同帧的列有部分重叠。我想在将列加入新框架时共享列之间的类别 -> ID 映射:
In [362]: af = pd.DataFrame(pd.Series(['a1','a2', 'b1'], dtype="category", name='a'))
In [365]: bf = pd.DataFrame(pd.Series(['b1','b2', 'a1'], dtype="category", name='b'))
In [373]: all_categories = pd.Categorical(['a1','a2','b1','b2'])
In [376]: show_mapping(af.a)
[('a1', 0), ('a2', 1), ('b1', 2)]
In [377]: af.a.cat = all_categories
In [378]: show_mapping(af.a)
[('a1', 0), ('a2', 1), ('b1', 2), ('b2', 3)]
In [379]: show_mapping(bf.b)
[('b2', 0), ('a1', 1), ('b1', 2)]
In [380]: bf.b.cat = all_categories
In [381]: show_mapping(bf.b)
[('a1', 0), ('a2', 1), ('b1', 2), ('b2', 3)]
现在我将这些帧与我假设现在相同的映射连接起来:
In [382]: df = af.join(bf)
但是当我打印列的映射时,它们会重置:
In [384]: show_mapping(df.a)
[('a1', 0), ('a2', 1), ('b1', 2)]
In [385]: show_mapping(df.b)
[('b2', 0), ('a1', 1), ('b1', 2)]
为什么在加入框架后会自动重做映射,我怎样才能达到我的预期?
def show_mapping(x):
print(list(sorted(zip(x.cat.categories, x.cat.codes), key=lambda x : x[1])))
编辑
所有的困惑都来自于使用了糟糕的展示功能。下面的 show 函数实际上工作正常。将其与 set_categories
方法而不是 .cat = ...
方法结合使用,结果一切正常:
def show_mapping(s):
print([(e, s.cat.codes[i]) for i, e in enumerate(s)])
您可以通过 all_categories
使用 set_categories
在每个分类列中使用相同的类别,因此在 join
之后得到相同的代码:
af = pd.DataFrame(pd.Series(['a1','a2', 'b1'], dtype="category", name='a'))
bf = pd.DataFrame(pd.Series(['b1','b2', 'a1'], dtype="category", name='b'))
def show_mapping(x):
return (list(sorted(zip(x.cat.categories, x.cat.codes), key=lambda x : x[1])))
print(af.a)
0 a1
1 a2
2 b1
Name: a, dtype: category
Categories (3, object): [a1, a2, b1]
all_categories = pd.Categorical(['a1','a2','b1','b2'])
af.a = af.a.cat.set_categories(all_categories)
bf.b = bf.b.cat.set_categories(all_categories)
已添加类别b2
:
print(af.a)
0 a1
1 a2
2 b1
Name: a, dtype: category
Categories (4, object): [a1, a2, b1, b2]
print(show_mapping(af.a))
[('a1', 0), ('a2', 1), ('b1', 2)]
print(show_mapping(bf.b))
[('b1', 0), ('a1', 2), ('a2', 3)]
df = af.join(bf)
print(show_mapping(df.a))
[('a1', 0), ('a2', 1), ('b1', 2)]
print(show_mapping(df.b))
[('b1', 0), ('a1', 2), ('a2', 3)]