重组数据框(可能是 pivot 或 unpivot)让每一列显示基于 0 和 1 的数据标签
Restructure dataframe (maybe pivot or unpivot) to have each column display the label of data based on 0's and 1's
我有调查数据。调查提出一个问题,受访者为每个问题选择一个或多个给定的类别。然后,调查会询问性别等人口统计问题。输出是一个数据框,其中人口统计信息作为列,每个问题中的每个类别都有一个由 0 和 1 组成的矩阵(0 = 未选择,1 = 已选择)。
为了帮助您更好地理解这看起来像什么,我有以下数据框:
df = pd.DataFrame({'Survey ID': [1,2,3],
'Q1_Topic A': [0,1,1],
'Q1_Topic B': [1,0,1],
'Q1_Topic C': [1,0,0],
'Q2_Topic X': [0,0,1],
'Q2_Topic Y': [0,1,0],
'Q2_Topic Z': [0,0,1],
'Gender': ['Male', 'Female', 'Male']
})
print(df)
我需要转换此数据框,以便根据选择的类别数量为每个问题显示一列,为每个调查显示多行。每行应该在相关问题列下有一个类别。
迷茫了吗?很难解释,但数据应该看起来像
df2 = pd.DataFrame({'Survey ID': [1,1,2,3,3],
'Q1': ['B','C','A','A','B'],
'Q2': [float('nan'), float('nan'), 'Y', 'X', 'Z'],
'Gender': ['Male', 'Male', 'Female', 'Male', 'Male']
})
print(df2)
基本上我需要将 df 转换为 df2。
注意:每个列标签的问题和主题都有一个通用分隔符“_”。
一如既往地非常感谢您在高级方面的帮助。如果没有这个社区,我有时会被严重卡住,我通过这个平台学到了很多东西。
这段代码怎么样?这不是花哨的代码,而是直观的。
import pandas as pd
import numpy as np
df1 = pd.DataFrame({'Survey ID': [1,2,3],
'Q1_Topic A': [0,1,1],
'Q1_Topic B': [1,0,1],
'Q1_Topic C': [1,0,0],
'Q2_Topic A': [0,0,1],
'Q2_Topic B': [0,1,0],
'Q2_Topic C': [0,0,1],
'Gender': ['Male', 'Female', 'Male']
})
values = []
for ind, row in df1.iterrows():
survey_ID = row['Survey ID']
Gender = row['Gender']
Q1 = row['Q1_Topic A'] * ['A'] + row['Q1_Topic B'] * ['B'] + row['Q1_Topic C'] * ['C']
Q2 = row['Q2_Topic A'] * ['A'] + row['Q2_Topic B'] * ['B'] + row['Q2_Topic C'] * ['C']
for i in range(max(len(Q1), len(Q2))):
if i >= len(Q1):
record = [survey_ID, np.nan, Q2[i], Gender]
elif i >= len(Q2):
record = [survey_ID, Q1[i], np.nan, Gender]
else:
record = [survey_ID, Q1[i], Q2[i], Gender]
values.append(record)
df2 = pd.DataFrame(values, columns = ['Survey ID', 'Q1', 'Q2', 'Gender'])
使用:
#convert to MultiIndex all not Q topic columns
df2 = df.set_index(['Survey ID','Gender'])
#split columns names to MultiIndex in columns
df2.columns = df2.columns.str.split(expand=True)
#reshape
df2 = df2.stack()
#filter only rows with at least one 1 per row and reshape for remove NaNs
#also replace 0 to NaNs
df2 = df2[df2.eq(1).any(axis=1)].replace(0, np.nan).stack().reset_index(level=2)
#added helper level to MultiIndex because possible duplicates by counter
df2['g'] = df2.groupby(level=[0,1,2]).cumcount()
#final reshape
df2 = (df2.set_index('g', append=True)['level_2']
.unstack(2)
.reset_index(level=2, drop=True)
.reset_index())
print (df2)
Survey ID Gender Q1_Topic Q2_Topic
0 1 Male B NaN
1 1 Male C NaN
2 2 Female A Y
3 3 Male A X
4 3 Male B Z
我有调查数据。调查提出一个问题,受访者为每个问题选择一个或多个给定的类别。然后,调查会询问性别等人口统计问题。输出是一个数据框,其中人口统计信息作为列,每个问题中的每个类别都有一个由 0 和 1 组成的矩阵(0 = 未选择,1 = 已选择)。
为了帮助您更好地理解这看起来像什么,我有以下数据框:
df = pd.DataFrame({'Survey ID': [1,2,3],
'Q1_Topic A': [0,1,1],
'Q1_Topic B': [1,0,1],
'Q1_Topic C': [1,0,0],
'Q2_Topic X': [0,0,1],
'Q2_Topic Y': [0,1,0],
'Q2_Topic Z': [0,0,1],
'Gender': ['Male', 'Female', 'Male']
})
print(df)
我需要转换此数据框,以便根据选择的类别数量为每个问题显示一列,为每个调查显示多行。每行应该在相关问题列下有一个类别。
迷茫了吗?很难解释,但数据应该看起来像
df2 = pd.DataFrame({'Survey ID': [1,1,2,3,3],
'Q1': ['B','C','A','A','B'],
'Q2': [float('nan'), float('nan'), 'Y', 'X', 'Z'],
'Gender': ['Male', 'Male', 'Female', 'Male', 'Male']
})
print(df2)
基本上我需要将 df 转换为 df2。 注意:每个列标签的问题和主题都有一个通用分隔符“_”。
一如既往地非常感谢您在高级方面的帮助。如果没有这个社区,我有时会被严重卡住,我通过这个平台学到了很多东西。
这段代码怎么样?这不是花哨的代码,而是直观的。
import pandas as pd
import numpy as np
df1 = pd.DataFrame({'Survey ID': [1,2,3],
'Q1_Topic A': [0,1,1],
'Q1_Topic B': [1,0,1],
'Q1_Topic C': [1,0,0],
'Q2_Topic A': [0,0,1],
'Q2_Topic B': [0,1,0],
'Q2_Topic C': [0,0,1],
'Gender': ['Male', 'Female', 'Male']
})
values = []
for ind, row in df1.iterrows():
survey_ID = row['Survey ID']
Gender = row['Gender']
Q1 = row['Q1_Topic A'] * ['A'] + row['Q1_Topic B'] * ['B'] + row['Q1_Topic C'] * ['C']
Q2 = row['Q2_Topic A'] * ['A'] + row['Q2_Topic B'] * ['B'] + row['Q2_Topic C'] * ['C']
for i in range(max(len(Q1), len(Q2))):
if i >= len(Q1):
record = [survey_ID, np.nan, Q2[i], Gender]
elif i >= len(Q2):
record = [survey_ID, Q1[i], np.nan, Gender]
else:
record = [survey_ID, Q1[i], Q2[i], Gender]
values.append(record)
df2 = pd.DataFrame(values, columns = ['Survey ID', 'Q1', 'Q2', 'Gender'])
使用:
#convert to MultiIndex all not Q topic columns
df2 = df.set_index(['Survey ID','Gender'])
#split columns names to MultiIndex in columns
df2.columns = df2.columns.str.split(expand=True)
#reshape
df2 = df2.stack()
#filter only rows with at least one 1 per row and reshape for remove NaNs
#also replace 0 to NaNs
df2 = df2[df2.eq(1).any(axis=1)].replace(0, np.nan).stack().reset_index(level=2)
#added helper level to MultiIndex because possible duplicates by counter
df2['g'] = df2.groupby(level=[0,1,2]).cumcount()
#final reshape
df2 = (df2.set_index('g', append=True)['level_2']
.unstack(2)
.reset_index(level=2, drop=True)
.reset_index())
print (df2)
Survey ID Gender Q1_Topic Q2_Topic
0 1 Male B NaN
1 1 Male C NaN
2 2 Female A Y
3 3 Male A X
4 3 Male B Z