上下文
我有一个包含成绩单的数据框。 df中的每一行都有唯一的ID,记录行和时间戳,每个ID在一天(或几天)内可以有多个对应关系。
以下示例代码!
我有什么:
#What I have starting out with. Df is ordered by CustomerID and Timestamp
pd.DataFrame({'AgentID': 0, 'CustomerID': 1, 'Date': ['2018-01-21', '2018-01-21', '2018-01-22', '2018-01-22'], 'Timestamp': ['2018-01-21 16:28:54', '2018-01-21 16:48:54', '2018-01-22 12:18:54', '2018-01-22 12:22:54'], 'Transcript_Line':['How can I help you?', 'I need help with this pandas problem...', 'Did you get that problem resolved?', 'Nope I still suck at pandas']})
我需要什么:
#This is the final result
pd.DataFrame({'AgentID': 0, 'CustomerID': 1, 'Date': ['2018-01-21', '2018-01-22'], 'Transcript_Line': ['How can I help you?\nI need help with this pandas problem...', 'Did you get that problem resolved?\nNope I still suck at pandas']})
我需要组织和组合对应于同一天(按顺序)的所有成绩单(每行中的字符串)。
这是我到目前为止所尝试的 问题出在这里:
def concatConvos(x):
if len(set(x.Date)) == 1:
return pd.Series({'Email' : x['CustomerID'].values[0],
'Date': x['Date'].values[0],
'Conversation' : '\n'.join(x['Transcript_Line'])})
else:
rows = []
for date in set(x.Date):
rows.append(pd.Series({'Email': x['CustomerID'].values[0],
'Date': date,
'Conversation': '\n'.join(x[x.Date == date].Transcript_Line)}))
return tuple(rows)
data3 = data2.groupby('CustomerID').apply(concatConvos)
我能够在客户只有1个通信日期(意味着他没有多次联系,第一种情况)的情况下工作。
如果我尝试处理的案例多于1,那么我最终会遇到属性错误,因为该函数正在返回多个系列对象。
有没有更简单的方法来解决这个问题?
答案 0 :(得分:1)
这不是最漂亮的解决方案,也不是最有效的解决方案,但我过去曾经使用过这样的解决方案。我相信可能有一个更有效的解决方案,而不是使用循环。我会给你原始代码,然后一步一步地分解它:
transcript_join = df.groupby(['CustomerID', 'Date']).apply(lambda f: f['Transcript_Line'].values.tolist()).to_dict()
for x in transcript_join.keys():
df.loc[(df['CustomerID']==x[0]) & (df['Date'] == x[1]), 'Combine'] = '\n'.join(transcript_join.get(x))
df.drop_duplicates(df.iloc[:,[0,1,2,5]])
# output below
AgentID CustomerID Date Timestamp Transcript_Line Combine
0 0 1 2018-01-21 2018-01-21 16:28:54 How can I help you? How can I help you?\nI need help with this pan...
2 0 1 2018-01-22 2018-01-22 12:18:54 Did you get that problem resolved? Did you get that problem resolved?\nNope I sti...
首先,我使用变量transcript_join
创建所有响应的字典。关键是客户ID,然后是日期。价值是成绩单清单。
然后我遍历键并获取字典中客户ID和日期相同的位置,并使用.join
将成绩单组合在一个新列中。
最后,我删除了重复项,因为现在会有重复项,因为每个客户ID和日期对将包含相同的Combine
列。我使用iloc
来删除输出中不需要的列,例如原始Transcript
列以及Timestamp
答案 1 :(得分:1)
您应该可以使用groupby完成此操作。这是您原来的DataFrame。我只是为了方便而将它命名为df。
df = pd.DataFrame({'AgentID': 0, 'CustomerID': 1, 'Date': ['2018-01-21', '2018-01-21', '2018-01-22', '2018-01-22'], 'Timestamp': ['2018-01-21 16:28:54', '2018-01-21 16:48:54', '2018-01-22 12:18:54', '2018-01-22 12:22:54'], 'Transcript_Line':['How can I help you?', 'I need help with this pandas problem...', 'Did you get that problem resolved?', 'Nope I still suck at pandas']})
我有点不清楚你是否需要对AgentID和CustomerID进行排序,或者只对其中一个进行排序,但希望你能看到如何修改它。
初始排序可确保Transcript_Line按顺序排列。然后,groupby在同一天查找同一AgentID和CustomerID的所有声明集。 as_index = False,为您提供输出中列的正确格式。你想要的输出是组合成绩单行,你可以用总和完成。
df.sort_values(by=['AgentID', 'CustomerID',
'Timestamp']).groupby(['AgentID', 'CustomerID',
'Date'], as_index=False)['Transcript_Line'].sum()
如果你真的需要它们之间的'\ n'字符,那么你可以通过首先将它们添加到每个抄本行,与上面做同一组,然后在组合结束时删除字符来解决这个问题。字符串。
df['Transcript_Line'] = df['Transcript_Line'] + '\n'
grouped = df.sort_values(by=['AgentID', 'CustomerID',
'Timestamp']).groupby(['AgentID', 'CustomerID',
'Date'], as_index=False)['Transcript_Line'].sum()
grouped['Transcript_Line'] = grouped['Transcript_Line'].apply(lambda
x: x[:-1])