基于 2 列合并和对齐列
Merge and align columns based on 2 columns
我有一个如下的 df:
ID P1 P2 P3_1_A P3_2_B P4_1_A P4_2_B
1 110 111 1 0 1 1
2 111 112 0 0 1 0
3 110 112 0 1 0 0
4 112 111 1 1 1 1
因此,P1 和 P2 有 3 个不同的值 110
、111
和 112
。
P3 和 P4 列的数量始终相等(在上述情况下为 2),但可能因数据而异。
我想要一个结果数据框,其中所有 P3 值都与 P1 对齐,所有 P4 值都与 P2 对齐,列重命名,如下所示
ID P P_A P_B
1 110 1 0
1 111 1 1
2 111 0 0
2 112 1 0
3 110 0 1
3 112 0 0
4 112 1 1
4 111 1 1
我知道如何合并 P1 和 P2 并到达 P 列,但不知道如何将 P3 和 P4 与 P1 和 P2 对齐并到达 P_1 和 P_2
您可以重命名 _
个子字符串的列,因此可以将 ID
转换为索引并将所有值拆分为 MultiIndex
,最后按 DataFrame.stack
:[=19 重塑=]
df1 = df.rename(columns={'P1':'P3_','P2':'P4_'}).set_index('ID')
df1.columns = df1.columns.str.split('_', expand=True, n=1)
df1 = df1.stack(0).add_prefix('P').reset_index(level=1, drop=True).reset_index()
print (df1)
ID P P1_A P2_B
0 1 110 1 0
1 1 111 1 1
2 2 111 0 0
3 2 112 1 0
4 3 110 0 1
5 3 112 0 0
6 4 112 1 1
7 4 111 1 1
编辑:对于更通用的解决方案,可以提取不带双 _
的列名称并传递给 set_index
:
print (df)
ID P1 P2 P3_1_A P3_2_B P4_1_A P4_2_B A
0 1 110 111 1 0 1 1 9
1 2 111 112 0 0 1 0 7
2 3 110 112 0 1 0 0 8
3 4 112 111 1 1 1 1 7
df1 = df.rename(columns={'P1':'P3__','P2':'P4__'})
cols = df1.columns[df1.columns.str.count('_') != 2]
df1 = df1.set_index(cols.tolist())
df1.columns = df1.columns.str.split('_', expand=True, n=1)
df1 = df1.stack(0).add_prefix('P').reset_index(level=-1, drop=True).reset_index()
print (df1)
A ID P1_A P2_B P_
0 9 1 1 0 110
1 9 1 1 1 111
2 7 2 0 0 111
3 7 2 1 0 112
4 8 3 0 1 110
5 8 3 0 0 112
6 7 4 1 1 112
7 7 4 1 1 111
您可以使用 pivot_longer function from pyjanitor; at the moment you have to install the latest development version from github :
列具有模式(一些以数字(1 或 2)结尾,而另一些以 'A' 或 'B' 结尾)。我们可以利用这种模式并重塑数据。
我们将新列名列表传递给 names_to
,并将与模式匹配的正则表达式列表传递给 names_pattern
:
# install the latest dev version of pyjanitor
# pip install git+https://github.com/ericmjl/pyjanitor.git
import janitor
df.pivot_longer(
index="ID",
names_to=("P", "P_A", "P_B"),
names_pattern=("^P\d$", ".*A$", ".*B$"),
sort_by_appearance=True,
)
ID P P_A P_B
0 1 110 1 0
1 1 111 1 1
2 2 111 0 0
3 2 112 1 0
4 3 110 0 1
5 3 112 0 0
6 4 112 1 1
7 4 111 1 1
在上面的代码中,新的 P
列从具有列 P1 或 P2(它们以数字结尾)的先前数据框中获取所有值,P_A
获取以 'A',而 P_B
接受以 'B'.
结尾的列
我有一个如下的 df:
ID P1 P2 P3_1_A P3_2_B P4_1_A P4_2_B
1 110 111 1 0 1 1
2 111 112 0 0 1 0
3 110 112 0 1 0 0
4 112 111 1 1 1 1
因此,P1 和 P2 有 3 个不同的值 110
、111
和 112
。
P3 和 P4 列的数量始终相等(在上述情况下为 2),但可能因数据而异。
我想要一个结果数据框,其中所有 P3 值都与 P1 对齐,所有 P4 值都与 P2 对齐,列重命名,如下所示
ID P P_A P_B
1 110 1 0
1 111 1 1
2 111 0 0
2 112 1 0
3 110 0 1
3 112 0 0
4 112 1 1
4 111 1 1
我知道如何合并 P1 和 P2 并到达 P 列,但不知道如何将 P3 和 P4 与 P1 和 P2 对齐并到达 P_1 和 P_2
您可以重命名 _
个子字符串的列,因此可以将 ID
转换为索引并将所有值拆分为 MultiIndex
,最后按 DataFrame.stack
:[=19 重塑=]
df1 = df.rename(columns={'P1':'P3_','P2':'P4_'}).set_index('ID')
df1.columns = df1.columns.str.split('_', expand=True, n=1)
df1 = df1.stack(0).add_prefix('P').reset_index(level=1, drop=True).reset_index()
print (df1)
ID P P1_A P2_B
0 1 110 1 0
1 1 111 1 1
2 2 111 0 0
3 2 112 1 0
4 3 110 0 1
5 3 112 0 0
6 4 112 1 1
7 4 111 1 1
编辑:对于更通用的解决方案,可以提取不带双 _
的列名称并传递给 set_index
:
print (df)
ID P1 P2 P3_1_A P3_2_B P4_1_A P4_2_B A
0 1 110 111 1 0 1 1 9
1 2 111 112 0 0 1 0 7
2 3 110 112 0 1 0 0 8
3 4 112 111 1 1 1 1 7
df1 = df.rename(columns={'P1':'P3__','P2':'P4__'})
cols = df1.columns[df1.columns.str.count('_') != 2]
df1 = df1.set_index(cols.tolist())
df1.columns = df1.columns.str.split('_', expand=True, n=1)
df1 = df1.stack(0).add_prefix('P').reset_index(level=-1, drop=True).reset_index()
print (df1)
A ID P1_A P2_B P_
0 9 1 1 0 110
1 9 1 1 1 111
2 7 2 0 0 111
3 7 2 1 0 112
4 8 3 0 1 110
5 8 3 0 0 112
6 7 4 1 1 112
7 7 4 1 1 111
您可以使用 pivot_longer function from pyjanitor; at the moment you have to install the latest development version from github :
列具有模式(一些以数字(1 或 2)结尾,而另一些以 'A' 或 'B' 结尾)。我们可以利用这种模式并重塑数据。
我们将新列名列表传递给 names_to
,并将与模式匹配的正则表达式列表传递给 names_pattern
:
# install the latest dev version of pyjanitor
# pip install git+https://github.com/ericmjl/pyjanitor.git
import janitor
df.pivot_longer(
index="ID",
names_to=("P", "P_A", "P_B"),
names_pattern=("^P\d$", ".*A$", ".*B$"),
sort_by_appearance=True,
)
ID P P_A P_B
0 1 110 1 0
1 1 111 1 1
2 2 111 0 0
3 2 112 1 0
4 3 110 0 1
5 3 112 0 0
6 4 112 1 1
7 4 111 1 1
在上面的代码中,新的 P
列从具有列 P1 或 P2(它们以数字结尾)的先前数据框中获取所有值,P_A
获取以 'A',而 P_B
接受以 'B'.