我的目标是根据输入的频率生成句子。例如,我有这样的输入:
>>> df = pd.DataFrame({"s":["a", "a", "b", "b", "c", "c"], "m":[["x", "y"], ["x", "z"], ["y", "w", "z"], ["y"], ["z"], ["z"]]})
>>> df.set_index("s")
>>> df
m
s
a [x, y]
a [x, z]
b [y, w, z]
b [y]
c [z]
c [z]
我想要一个函数gen_sentence(s)
,该函数采用s
并根据m
列中字母的频率生成随机的非空句子。因此,gen_sentence("a")
应该生成所有包含x
的句子,其中50%应该包含y
和50%z
。
我的直觉是将DataFrame转换为频率的DataFrame,因此对于这样的示例:
w x y z
s
a 0.0 1 0.5 0.5
b 0.5 0 1.0 0.5
c 0.0 0 0.0 1.0
然后在给定s
的情况下为每列滚动一个随机数:
def gen_sentence(fdf, s):
return fdf.columns[np.random.random(len(fdf.columns)) < fdf.loc[s]]
但是,我不知道如何在频率DataFrame中转换DataFrame。
解决方案可能是使用df.agg["s"]
,但是我对聚合应用什么功能?
实际上,数据集非常大,有超过一百万行,m
中约有500个不同的单词,而s
约有100个不同的值,并且频率表将稀疏:大多数{{1}对于s
中的大多数单词,}的频率为零。此外,我需要至少生成几十万个句子,因此我试图找到一种实现可以尽快生成一个句子的实现。另外,该解决方案不必使用Panda的解决方案,我只是认为大多数功能的矢量化实现是最快的解决方案。
因此,简而言之,首先,如何将DataFrame转换为频率DataFrame,其次,是否有一种更快的生成句子的方法?
我已经测试了我的实现,看它是否足够快并且是否不错:一个频率为500行100列的DataFrame可以在我的机器上约1.2秒内生成5000个句子。
如果您想针对我的方法测试自己的方法,这是我的测试:
m
答案 0 :(得分:1)
要转换为频率数据帧,请尝试以下方法(不是最佳解决方案,但它可以工作):
for letter in ['x', 'y', 'w', 'z']:
df.loc[:, letter] = df.m.apply(lambda x: x.count(letter))
df = df.drop(['m'], axis=1)
df_1 = df.groupby('s').agg(lambda x: sum(x)).reset_index()
print(df_1)
输出:
s x y w z
0 a 2 1 0 1
1 b 0 2 1 1
2 c 0 0 0 2
另一种选择(使用for
和stack
的{{1}}循环):
pivot_table
输出:
import numpy as np
df_1 = (df.m.apply(pd.Series).stack().to_frame('m')).reset_index().set_index('level_0')['m']
df_1 = pd.concat([df['s'], df_1], axis=1).reset_index()[['s', 'm']]
df_1.insert(1, 'freq', 1)
df_1 = pd.pivot_table(df_1, values='freq', index='s', columns='m', aggfunc=np.sum).fillna(0)
df_1 = df_1.div(df_1.max(axis=1), axis=0)
df_1.columns.name=None
print(df_1)
答案 1 :(得分:0)
在阿拉(Alla Tarighati)的帮助下,我现在有了问题的第一部分解决方案:
letters = set(x for l in df["m"] for x in l)
for letter in letters:
df.loc[:, letter] = df.m.apply(lambda x: letter in x)
df = df.drop(["m"], axis=1)
gdf = df.groupby("s")
fdf = gdf.agg(lambda x: sum(x))
fdf = fdf.divide(gdf.size(), axis="index")
print(fdf)
输出:
y x z w
s
a 0.5 1.0 0.5 0.0
b 1.0 0.0 0.5 0.5
c 0.0 0.0 1.0 0.0
请注意,在第三行中,我将lambda函数更改为letter in x
,以使句子中的重复字母不会被重复计数。
和Alla Tarighati一样,这不是一个非常快的解决方案,因此欢迎进行改进!