Python 如何在pandas中使用apply函数返回多行?
上下文 我有一个包含成绩单的数据框。df中的每一行都有一个唯一的ID、记录行和时间戳,每个ID在一天内(或几天内)可以有多个对应关系Python 如何在pandas中使用apply函数返回多行?,python,pandas,python-3.6,pandas-groupby,Python,Pandas,Python 3.6,Pandas Groupby,上下文 我有一个包含成绩单的数据框。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-2
下面的示例代码强>
我所拥有的:
#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']})
我需要什么:
#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个的情况,那么很可能会出现属性错误,因为函数返回多个series对象
有更简单的方法吗?这不是最漂亮的解决方案,也不是最有效的解决方案,但我过去也用过类似的方法。我相信可能会有一个更有效的解决方案,而不是使用循环。我将为您提供原始代码,然后逐步分解:
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\u join
创建一个包含所有响应的字典。关键是客户ID,然后是日期。该值是成绩单的列表
然后,我循环遍历这些键,得到客户ID和日期在字典中相同的位置,并使用.join
将成绩单合并到一个新列中
最后,我删除了重复项,因为现在将有重复项,因为每个客户ID和日期对将包含相同的
Combine
列。我使用iloc
删除输出中不需要的列,例如原始Transcript
列以及Timestamp
,您应该能够使用groupby实现这一点。这是您的原始数据帧。为了方便起见,我把它命名为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进行排序,或者只对其中一个进行排序,但希望您能看到如何修改它
初始排序保证转录本_行将按顺序排列。groupby然后查找同一天相同AgentID和CustomerID的所有声明集。as_index=False为您提供输出中列的正确格式。您想要的输出是组合成绩单行,您可以使用sum来完成
df.sort_values(by=['AgentID', 'CustomerID',
'Timestamp']).groupby(['AgentID', 'CustomerID',
'Date'], as_index=False)['Transcript_Line'].sum()
如果您确实需要它们之间的“\n”字符,那么您可以先将它们添加到每个转录本行中,执行与上面相同的groupby操作,然后删除组合字符串末尾的字符
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])
您是否可以共享数据框的一个示例,其中显示您的问题和预期输出?有很多的文字,有些人(我也是)可能很难理解。是的…给我一秒钟。。。有一些PII信息我需要过滤掉。我更新了——使用了解析前的df示例。我不使用图片,而是粘贴文本。阅读,它可能会有帮助:)这是一个伟大的编辑,继续张贴这样的问题!如果你第一次以这种方式发布,你更有可能得到可靠的答案:)老实说。。。如果有人发布了另一个解决方案,我会非常感激,因为这将使我的一个流程更快。我只是希望我们有一个更快的解决方案。我觉得groupby方法应该可以工作,并且应该能够通过apply进行操作,以获得我们的结果。幸运的是,我仍在努力实现它。这个数据集大约有50万条记录,所以我试图把所有的数据都分块解析