[英]Most efficient way to merge multiple rows of a pandas dataframe in to one row, adding new columns to the row, based on values in the initial rows?
我有一个由受众特征和调查问题与答案组成的熊猫数据框。 问题是多项选择和多项选择。 初始数据帧中的每一行表示单个问题的单个答案。 因此,每个受访者和每个问题都有多行。 初始数据帧如下所示:
user_id question answer age gender
1 question_1 answer3 34 male
1 question_1 answer5 34 male
1 question_2 answer1 34 male
1 question_2 answer4 34 male
2 question_1 answer1 22 female
2 question_1 answer3 22 female
我想更改数据框,以便每一行代表一个受访者的所有答案。 在新数据框中,每个受访者只有一行,每个问题/答案组合只有一列。 如果受访者用相应的答案回答了问题,则问题/答案列的值将为1。 新的数据框应如下所示:
user_id age gender q1_ans1 q1_ans3 q1_ans5 q2_ans1 q2_ans4
1 34 male 0 1 1 1 1
2 22 female 1 1 0 0 0
我试图通过创建一个新的数据框,使用itertuples()遍历每一行,检查新数据框是否包含相关受访者的行来实现此目的,如果没有,则在新数据框中使用新列,以当前行中问题和答案字段的组合命名,值为1,如果确实如此,则为被调查者找到该行并添加新列,将其命名为问题和答案的组合从当前行回答并将值设置为1。
问题在于,这非常慢。 是否有使用数据帧实现此目的的更有效方法? 如果没有,那么还有其他解决方案吗? 任何帮助都感激不尽。 代码如下:
def process_raw_df(self):
raw_df = self.dc.get_data_frame()
new_df = pd.DataFrame(columns=['user_id', 'occupation_label',
'relationship_label', 'age',
'income_tier', 'income',
'has_children', 'country', 'city'])
new_df.set_index('user_id')
for row in raw_df.itertuples():
new_column_name = str(row[2]) + str(row[3])
if new_df.loc[new_df['user_id'] == row[0]]['user_id'].count()
== 0:
new_row = [[row[1], row[4], row[5], row[6], row[7], row[8],
row[9], row[10], row[11], 1]]
new_row_df = pd.DataFrame(new_row, columns=['user_id',
'occupation_label', 'relationship_label', 'age',
'income_tier', 'income', 'has_children', 'country',
'city', new_column_name])
new_df.append(new_row_df)
else:
new_df.loc[new_df['user_id'] == row[1], new_column_name] =
1
return new_df
好了,这是未经优化的代码,可以做简单的事情。 您需要熊猫的应用功能。
尝试申请并轮换
如果答案存在,则新列应为标志:
df['new_column'] = df.apply(lambda x : return user_flagger(x[2])
df.pivot(index='userid', columns='question', values='newcolumn')
然后标记所有非0的答案,等等。 我将把它的确切编码部分留给您作为练习。 :)
编辑:由于列名对您很重要,因此请多留一个列,以连接列问题和列答案。 之后,重点介绍串联的列名和从标志器函数获得的值。 花几分钟阅读有关熊猫进化论的文章,我相信答案将会清楚。 如果您仍然无法执行操作,我将在此处发布有效代码。
码:
df['pivot_column']=df['question'].str.replace('question_','q')+'_'+df['answer'].str.replace('answer','ans')
df['flag']=1
df2 = df.pivot(index='user_id', columns='pivot_column', values='flag')
此解决方案有一个小问题-它不需要性别和年龄,请参阅下面的代码,看看该代码是否比按组执行的速度更快。 如果是这样,您可以通过加入来恢复年龄和性别。
让我们使用groupby
和get_dummies
:
dfout = (df.groupby(['user_id','age','gender'])
.apply(lambda x: x.question+'_'+x.answer))
dfout = (dfout.to_frame()[0].str.get_dummies()
.reset_index(-1,drop=True)
.groupby(level=[0,1,2]).sum())
中间输出:
question_1_answer1 question_1_answer3 \
user_id age gender
1 34 male 0 1
2 22 female 1 1
question_1_answer5 question_2_answer1 question_2_answer4
user_id age gender
1 34 male 1 1 1
2 22 female 0 0 0
清理:
dfout.columns = dfout.columns.str.replace('question_','q')
dfout.columns = dfout.columns.str.replace('answer','ans')
dfout.reset_index(inplace=True)
print(dfout)
输出:
user_id age gender q1_ans1 q1_ans3 q1_ans5 q2_ans1 q2_ans4
0 1 34 male 0 1 1 1 1
1 2 22 female 1 1 0 0 0
df_1 = df.set_index(['user_id','age','gender'])
df_1['Q_Ans'] = df_1['question'].str.replace('question_','q') + '_' +df_1['answer'].str.replace('answer','ans')
df_1['Q_Ans'].str.get_dummies().groupby(level=[0,1,2]).sum().reset_index()
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.