将文本解析到它自己的字段中,计数并将 select 个字段重塑为宽格式
Parsing text into it's own field, counting, and reshaping select fields to wide format
我正在使用 Python 进行分析,通过计算互动次数和阅读消息来了解我们在社交媒体渠道中保持对话的时间。
我认为方法是让第一个 table 看起来像第二个 table。到达那里的步骤:
- 将我们的@username 解析到它自己的字段中。 99% 的时间,我们的回复以@username
开头
- 计算@username 出现的次数 - 这表示我们向用户发送的消息数
- 将入站和出站消息从长格式转换为宽格式。不确定我必须创建多少个字段,但只要我知道该技术,我以后就可以担心字段的数量。
现在时间戳对我来说不是那么重要,但它可能在未来。无论如何,我会使用与入站和出站消息相同的技术
之前 table
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
table
之后
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
你的改造过程应该包括几个步骤,我只给出其中一个步骤。
关于用户提取:
首先,您应该将 re 包中的 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('_',x)
,用 "_"
替换空格。在下一步中,您可以拆分 "_"
字符上的单元格:
import re
# x - your data
re.split('_', x)
您可以找到这两个函数的更多示例 here and here。
编辑:
由于您的用户 ID 并不总是有数字,因此您应该在从出站消息列中提取它时应用另一种逻辑。您可以使用以下方法从字符串中提取第一个单词:x.split(' ', 1)[0]
,其中 x - 您的字符串,以获取字符串的第一个单词,或者使用正则表达式:^\S*
注
您需要 groupby
user
和 df.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)
pd.concat([messages, df1], axis=1).reset_index()
分解辅助函数
# 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])
我正在使用 Python 进行分析,通过计算互动次数和阅读消息来了解我们在社交媒体渠道中保持对话的时间。
我认为方法是让第一个 table 看起来像第二个 table。到达那里的步骤:
- 将我们的@username 解析到它自己的字段中。 99% 的时间,我们的回复以@username 开头
- 计算@username 出现的次数 - 这表示我们向用户发送的消息数
- 将入站和出站消息从长格式转换为宽格式。不确定我必须创建多少个字段,但只要我知道该技术,我以后就可以担心字段的数量。
现在时间戳对我来说不是那么重要,但它可能在未来。无论如何,我会使用与入站和出站消息相同的技术
之前 table
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
table
之后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
你的改造过程应该包括几个步骤,我只给出其中一个步骤。
关于用户提取:
首先,您应该将 re 包中的 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('_',x)
,用 "_"
替换空格。在下一步中,您可以拆分 "_"
字符上的单元格:
import re
# x - your data
re.split('_', x)
您可以找到这两个函数的更多示例 here and here。
编辑:
由于您的用户 ID 并不总是有数字,因此您应该在从出站消息列中提取它时应用另一种逻辑。您可以使用以下方法从字符串中提取第一个单词:x.split(' ', 1)[0]
,其中 x - 您的字符串,以获取字符串的第一个单词,或者使用正则表达式:^\S*
注
您需要 groupby
user
和 df.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)
pd.concat([messages, df1], axis=1).reset_index()
分解辅助函数
# 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])