我有一个如下的示例:
col1 col2 Name_1 Gender_1 Age_1 I#2_Name I#2_Gender I#2_Age Unique_Col
A1 50 Amy F 20 NaN NaN NaN Key_01
A2 20 Judy F 35 Andy M 37 Key_02
A3 10 James M 45 Alice F 45 Key_03
A4 150 Sam M 23 NaN NaN NaN Key_04
A5 200 Annie F 40 John NaN NaN Key_05
如果有第二个名称,我想将数据帧从一行拆分为两行。
col1 col2 Name_new Gender_new Age_new Unique_Col
A1 50 Amy F 20 Key_01_N1
A2 20 Judy F 35 Key_02_N1
A2 20 Andy M 37 Key_02_N2
A3 10 James M 45 Key_03_N1
A3 10 Alice F 45 Key_03_N2
A4 150 Sam M 23 Key_04_N1
A5 200 Annie F 40 Key_05_N1
A5 200 John NaN NaN Key_05_N2
有时,第二性别和年龄的价值缺失
知道吗?
您可以使用pyjanitor中的pivot_langer来重塑数据:
(df.pivot_longer(index = ['col1', 'col2', 'Unique_Col'],
names_to = ['Name_new', 'Gender_new', 'Age_new'],
names_pattern = ['Name', 'Gender', 'Age'],
sort_by_appearance = True)
)
col1 col2 Unique_Col Name_new Gender_new Age_new
0 A1 50 Key_01 Amy F 20.0
1 A1 50 Key_01 NaN NaN NaN
2 A2 20 Key_02 Judy F 35.0
3 A2 20 Key_02 Andy M 37.0
4 A3 10 Key_03 James M 45.0
5 A3 10 Key_03 Alice F 45.0
6 A4 150 Key_04 Sam M 23.0
7 A4 150 Key_04 NaN NaN NaN
8 A5 200 Key_05 Annie F 40.0
9 A5 200 Key_05 John NaN NaN
在上面的代码中,将一个新列名列表传递给names_to
。对于每个新列名,都将一个模式(正则表达式(传递给names_pattern
。因此,对于Names_new
,函数将搜索包含Name
的任何列,并将所有数据拉入该列,Gender_new
和Age_new
也是如此。
你也可以只使用熊猫,并使用wide_to_long;首先对列进行重新排序,使Gender
、Name
和Age
位于前面:
new_df = df.rename(columns = lambda col: "_".join(col.split("_")[::-1])
if "#" in col else col)
new_df
col1 col2 Name_1 Gender_1 Age_1 Name_I#2 Gender_I#2 Age_I#2 Unique_Col
0 A1 50 Amy F 20 NaN NaN NaN Key_01
1 A2 20 Judy F 35 Andy M 37.0 Key_02
2 A3 10 James M 45 Alice F 45.0 Key_03
3 A4 150 Sam M 23 NaN NaN NaN Key_04
4 A5 200 Annie F 40 John NaN NaN Key_05
让我们重塑:
(pd.wide_to_long(new_df,
stubnames = ['Name', 'Gender', 'Age'],
i = ['col1', 'col2', 'Unique_Col'],
j = 'suffix',
sep = "_",
suffix = ".+")
.droplevel("suffix")
.reset_index()
)
col1 col2 Unique_Col Name Gender Age
0 A1 50 Key_01 Amy F 20.0
1 A1 50 Key_01 NaN NaN NaN
2 A2 20 Key_02 Judy F 35.0
3 A2 20 Key_02 Andy M 37.0
4 A3 10 Key_03 James M 45.0
5 A3 10 Key_03 Alice F 45.0
6 A4 150 Key_04 Sam M 23.0
7 A4 150 Key_04 NaN NaN NaN
8 A5 200 Key_05 Annie F 40.0
9 A5 200 Key_05 John NaN NaN
创建两个列为cols1
和cols2
的日期框(请参阅代码中的值(。
在第二个数据帧中,删除所有Name_x
、Gender_x
、Age_x
都是nan
的值,这意味着第二个名称不存在。将两个数据帧中的Name_x
、Gender_x
、Age_x
重命名为Name_new
、Gender_new
、Age_new
。
然后使用pd.concat
垂直连接日期框。
用途:
cols1 = ['col1', 'col2', 'Name_1', 'Gender_1', 'Age_1', 'Unique_Col']
cols2 = ['col1', 'col2', 'Name', 'Gender_2', 'Age_2', 'Unique_Col']
def rename_col(x):
return x.split("_")[0] + "_new" if '_' in x else x
df1 = df[cols1].rename(rename_col, axis = 'columns')
df2 = (df[cols2]
.dropna(subset = ['Name_2', 'Gender_2', 'Age_2'], how = 'all')
.rename(rename_col, axis = 'columns'))
输出:
>>> out
col1 col2 Name_new Gender_new Age_new Unique_new
0 A1 50 Amy F 20.0 Key_01
1 A2 20 Judy F 35.0 Key_02
1 A2 20 Andy M 37.0 Key_02
2 A3 10 James M 45.0 Key_03
2 A3 10 Alice F 45.0 Key_03
3 A4 150 Sam M 23.0 Key_04
4 A5 200 Annie F 40.0 Key_05
4 A5 200 John NaN NaN Key_05
如果你的性别和名字没有相同的模式,那么使用字典映射来重命名:
cols1 = ['col1', 'col2', 'Name_1', 'Gender_1', 'Age_1', 'Unique_Col']
cols2 = ['col1', 'col2', 'I#2_Name', 'I#2_Gender', 'I#2_Age', 'Unique_Col']
new_cols = ['col1', 'col2', 'Name_New', 'Gender_New', 'Age_New', 'Unique_Col']
df1 = df[cols1].rename(dict(zip(cols1, new_cols)), axis = 'columns')
df2 = (df[cols2]
.dropna(subset = cols2[2:5], how = 'all')
.rename(dict(zip(cols2, new_cols)), axis = 'columns'))
out = pd.concat([df1, df2]).sort_values(by = ['col1'])
尝试pandas melt函数。类似的东西
pd.melt(df, id_vars = ['Name_1','Name_2'])