pandas - 带有外连接的 DataFrame 扩展
Posted
技术标签:
【中文标题】pandas - 带有外连接的 DataFrame 扩展【英文标题】:pandas - DataFrame expansion with outer join 【发布时间】:2014-10-10 22:57:44 【问题描述】:首先,我是 pandas 的新手,我正在努力学习,所以我们将不胜感激。
我想生成一个表示地图witter tag subtoken -> poster
的pandas DataFrame,其中标记子标记表示集合hashtagA U i | i in split('_', hashtagA)
中的任何内容,来自匹配poster -> tweet
的表
例如:
In [1]: df = pd.DataFrame([["jim", "i was like #yolo_omg to her"], ["jack", "You are so #yes_omg #best_place_ever"], ["neil", "Yo #rofl_so_funny"]])
In [2]: df
Out[2]:
0 1
0 jim i was like #yolo_omg to her
1 jack You are so #yes_omg #best_place_ever
2 neil Yo #rofl_so_funny
我想从中得到类似的东西
0 1
0 jim yolo_omg
1 jim yolo
2 jim omg
3 jack yes_omg
4 jack yes
5 jack omg
6 jack best_place_ever
7 jack best
8 jack place
9 jack ever
10 neil rofl_so_funny
11 neil rofl
12 neil so
13 neil funny
我设法构建了这个真正完成这项工作的大多数人:
In [143]: df[1].str.findall('#([^\s]+)') \
.apply(pd.Series).stack() \
.apply(lambda s: [s] + s.split('_') if '_' in s else [s]) \
.apply(pd.Series).stack().to_frame().reset_index(level=0) \
.join(df, on='level_0', how='right', lsuffix='_l')[['0','0_l']]
Out[143]:
0 0_l
0 0 jim yolo_omg
1 jim yolo
2 jim omg
0 jack yes_omg
1 jack yes
2 jack omg
1 0 jack best_place_ever
1 jack best
2 jack place
3 jack ever
0 0 neil rofl_so_funny
1 neil rofl
2 neil so
3 neil funny
但我有一种非常强烈的感觉,即有更好的方法可以做到这一点,特别是考虑到真实的数据集非常庞大。
【问题讨论】:
似乎是一个合理的问题,我很惊讶还没有人回答。您可能需要进行编辑,将行拆分成更小的部分,使其更具可读性。 一个初步的想法是,您正在将字符串方法与其他数据混杂在一起。我想知道您是否只想使用常规 python 在一个地方执行所有字符串操作,然后读入数据帧?不确定它是否会更快,但几乎可以肯定会更简单。 也许我应该这么说,但我从带有frame_query
的 sql 数据库中读取了我的数据,所以我从一开始就把我的数据放在了一个数据框中。正如我所说,我对哪个是最佳实践没有强烈的意见。无论如何用常规python处理数据是个好主意吗?反正我用的是lambda
...
更有经验的 pandas 用户可能会给你更优雅的代码,但我怀疑你使用的工具不正确。您的单行 python 可能会在某个阶段工作,但不会是可维护的。多几行将为您提供具有标准 python 结构的代码,如果您需要该格式,您可以将其放回数据框中。
【参考方案1】:
pandas 确实有本机执行此操作的功能。 Series.str.findall() 这基本上应用了一个正则表达式并捕获您在其中指定的组。
如果我有你的数据框:
df = pd.DataFrame([["jim", "i was like #yolo_omg to her"], ["jack", "You are so #yes_omg #best_place_ever"], ["neil", "Yo #rofl_so_funny"]])
我要做的是首先设置列的名称,如下所示:
df.columns = ['user', 'tweet']
或者在创建数据框时进行:
df = pd.DataFrame([["jim", "i was like #yolo_omg to her"], ["jack", "You are so #yes_omg #best_place_ever"], ["neil", "Yo #rofl_so_funny"]], columns=['user', 'tweet'])
然后我将简单地使用正则表达式应用提取函数:
df['tag'] = df["tweet"].str.findall("(#[^ ]*)")
我会使用否定字符组而不是肯定字符组,这更有可能在特殊情况下存活。
【讨论】:
【参考方案2】:在 python 中使用列表推导然后恢复到 pandas 怎么样?需要几行代码,但可能更具可读性。
import re
获取哈希标签
tags = [re.findall('#([^\s]+)', t) for t in df[1]]
为每个用户制作带有子标记的标签列表
st = [[t] + [s.split('_') for s in t] for t in tags]
subtokens = [[i for s in poster for i in s] for poster in st]
放回带有海报名称的DataFrame
df2 = pd.DataFrame(subtokens, index=df[0]).stack()
In [250]: df2
Out[250]:
jim 0 yolo_omg
1 yolo
2 omg
jack 0 yes_omg
1 best_place_ever
2 yes
3 omg
4 best
5 place
6 ever
neil 0 rofl_so_funny
1 rofl
2 so
3 funny
dtype: object
【讨论】:
以上是关于pandas - 带有外连接的 DataFrame 扩展的主要内容,如果未能解决你的问题,请参考以下文章