将文本解析为自己的字段,计算并将选择字段重新整形为宽格式

时间:2016-09-03 19:11:47

标签: python pandas dataframe aggregate reshape

我正在使用Python进行分析,通过计算交互次数和阅读消息来了解我们在社交媒体渠道中保持对话的时间。

我认为方法是让第一个表看起来像第二个表。到达那里的步骤:

  1. 将@username解析为它自己的字段。 99%的时间,我们的回复都以@username
  2. 开头
  3. 计算@username显示的次数 - 这表示我们发送给用户的消息数
  4. 将入站和出站邮件从长格式转为宽格式。不确定我需要创建多少个字段,但只要我知道该技术,我就可以稍后担心字段数。
  5. 现在时间戳对我来说并不重要,但可能在未来。无论如何,我会使用与入站和出站消息相同的技术

    在表格之前

        Inbound Message      Outbound message     Inbound Time     Outbound Time     Account
        Hello, how are you   @userA I'm good!     mm/dd/yy hh:mm   mm/dd/yy hh:mm    FB
        Where is the cat?    @userB what cat?     mm/dd/yy hh:mm   mm/dd/yy hh:mm    Twitter
        What is a pie        @user3 it is a food  mm/dd/yy hh:mm   mm/dd/yy hh:mm    Twitter
        The black cat        @userB I don't know  mm/dd/yy hh:mm   mm/dd/yy hh:mm    Twitter
    

    表后

    User    Messages  Account   Inbound 1           Outbound 1           Inbound 2      Outbound 2           Inbound 3 Outbound 3 
    userA   1         FB        Hello, how are you  @user1 I'm good!     null           null                  null     null 
    userB   2         Twitter   Where is the cat?   @user2 what cat?     The black cat  @user2 I don't know   null     null
    user3   1         Twitter   What is a pie       @user3 it is a food  null           null                  null     null 
    
    

2 个答案:

答案 0 :(得分:1)

您的转型过程应包括几个步骤,我只会向其中一个提出一个想法。

关于用户提取: 首先,您应该将重新包中的re.sub(pattern, repl, string)函数应用于出站消息列中的原始数据(在循环中)。 sub函数与compile函数一起使用,其中指定了正则表达式:

import re
# x - your string
# here you write your regular expression: a whitespace between a number and a word character (not syntax characters).
y = re.compile(r"([0-9])(\s)(\w)")
# here you replace the second capture group from the regex the whitespace with a _ symbol
y.sub('_\2',x)

,用"_"替换空格。在下一步中,您可以拆分"_"字符上的单元格:

import re
# x - your data
re.split('_', x) 

您可以找到herehere两种功能的更多示例。

修改

由于您的用户ID并不总是包含数字,因此您应该从“出站”消息列中提取另一个逻辑。您可以使用以下代码从字符串中提取第一个单词:x.split(' ', 1)[0],其中x - 您的字符串,以获取strin的第一个单词,或使用正则表达式:^\S*

答案 1 :(得分:1)

<强> 注意
您需要groupby userdf.Account,因为可以为同一用户提供来自不同帐户的邮件。

# helper function to flatten multiindex objects
def flatten_multiindex(midx, sep=' '):
    n = midx.nlevels
    tups = zip(*[midx.get_level_values(i).astype(str) for i in range(n)])
    return pd.Index([sep.join(tup) for tup in tups])

in_out = ['Inbound Message', 'Outbound message']

# this gets a fresh ordering for each group
handler = lambda df: df.reset_index(drop=True)

# Use regular expression to extract user
user = df['Outbound message'].str.extract(r'(?P<User>@\w+)', expand=False)

df1 = df.groupby([user, df.Account])[in_out].apply(handler) \
        .unstack().sort_index(1, 1)
df1.columns = flatten_multiindex(df1.columns)

# I separated getting group sizes from long to wide pivot
messages = df.groupby([user, df.Account]).size().to_frame('Messages')

pd.concat([messages, df1], axis=1)

enter image description here

pd.concat([messages, df1], axis=1).reset_index()

enter image description here

分解辅助功能

# helper function to flatten multiindex objects
def flatten_multiindex(midx, sep=' '):

    # get the number of levels in the index
    n = midx.nlevels

    # for each level in the index, get the values and
    # convert it to strings so I can later ' '.join on it
    #
    # zip forms the tuples so I can pass each result to ' '.join
    tups = zip(*[midx.get_level_values(i).astype(str) for i in range(n)])
    # do the ' '.join and return as an index object
    return pd.Index([sep.join(tup) for tup in tups])