python - 对于大型文本数据,如何使 pandas df 列中的文本处理更快?
问题描述
我有一个超过 1GB 的聊天数据 (chat.txt) 的大文本文件,格式如下:
john|12-02-1999|hello#,there#,how#,are#,you#,tom$
tom|12-02-1999|hey#,john$,hows#, it#, goin#
mary|12-03-1999|hello#,boys#,fancy#,meetin#,ya'll#,here#
...
...
john|12-02-2000|well#,its#,been#,nice#,catching#,up#,with#,you#,and#, mary$
mary|12-03-2000|catch#,you#,on#,the#,flipside#,tom$,and#,john$
我想处理这个文本并分别为每个用户总结某些关键字的字数(比如 500 个字 - 你好,很好,比如.... 晚餐,不)。此过程还涉及从每个单词中删除所有尾随特殊字符
输出看起来像
user hello nice like ..... dinner No
Tom 10000 500 300 ..... 6000 0
John 6000 1200 200 ..... 3000 5
Mary 23 9000 10000 ..... 100 9000
这是我目前的 pythonic 解决方案:
chat_data = pd.read_csv("chat.txt", sep="|", names =["user","date","words"])
user_lst = chat_data.user.unique()
user_grouped_data= pd.DataFrame(columns=["user","words"])
user_grouped_data['user']=user_lst
for i,row in user_grouped_data.iterrows():
id = row["user"]
temp = chat_data[chat_data["user"]==id]
user_grouped_data.loc[i,"words"] = ",".join(temp["words"].tolist())
result = pd.DataFrame(columns=[ "user", "hello", "nice", "like","...500 other keywords...", "dinner", "no"])
result["user"]= user_lst
for i, row in result.iterrows():
id = row["user"]
temp = user_grouped_data[user_grouped_data["user"]==id]
words = temp.values.tolist()[0][1]
word_lst = words.split(",")
word_lst = [item[0:-1] for item in word_lst]
t_dict = Counter(word_lst)
keys = t_dict.keys()
for word in keys:
result.at[i,word]= t_dict.get(word)
result.to_csv("user_word_counts.csv")
这适用于小数据,但是当我的 chat_data 超过 1gb 时,此解决方案变得非常缓慢且无法使用。
下面有没有我可以改进的部分,可以帮助我更快地处理数据?
- 按用户分组文本数据
- 通过删除尾随特殊字符来清理每行中的文本数据
- 计算单词并将单词计数分配给右列
解决方案
您可以split
将逗号分隔的列转换为列表,explode
通过该列表列、groupby
名称和分解列表中的值unstack
或数据框转换为所需格式的数据框,并使用, ,pivot_table
对多索引列进行一些最终清理等等droplevel()
reset_index()
下面所有的都是矢量化的 pandas 方法,所以希望它很快。注意:当我从剪贴板读取并传递时,下面代码中的三列是 [0,1,2]headers=None
输入:
df = pd.DataFrame({0: {0: 'john', 1: 'tom', 2: 'mary', 3: 'john', 4: 'mary'},
1: {0: '12-02-1999',
1: '12-02-1999',
2: '12-03-1999',
3: '12-02-2000',
4: '12-03-2000'},
2: {0: 'hello#,there#,how#,are#,you#,tom$ ',
1: 'hey#,john$,hows#, it#, goin#',
2: "hello#,boys#,fancy#,meetin#,ya'll#,here#",
3: 'well#,its#,been#,nice#,catching#,up#,with#,you#,and#, mary$',
4: 'catch#,you#,on#,the#,flipside#,tom$,and#,john$'}})
代码:
df[2] = df[2].replace(['\#', '\$'],'', regex=True).str.split(',')
df = (df.explode(2)
.groupby([0, 2])[2].count()
.rename('Count')
.reset_index()
.set_index([0,2])
.unstack(1)
.fillna(0))
df.columns = df.columns.droplevel()
df = df.reset_index()
df
Out[1]:
2 0 goin it mary and are been boys catch catching ... on \
0 john 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 1.0 ... 0.0
1 mary 0.0 0.0 0.0 1.0 0.0 0.0 1.0 1.0 0.0 ... 1.0
2 tom 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 ... 0.0
2 the there tom tom up well with ya'll you
0 0.0 1.0 0.0 1.0 1.0 1.0 1.0 0.0 2.0
1 1.0 0.0 1.0 0.0 0.0 0.0 0.0 1.0 1.0
您也可以使用.pivot_table
而不是.unstack()
,这样可以为您节省这行代码df.columns = df.columns.droplevel()
:
df[2] = df[2].replace(['\#', '\$'],'', regex=True).str.split(',')
df = (df.explode(2)
.groupby([0, 2])[2].count()
.rename('Count')
.reset_index()
.pivot_table(index=0, columns=2, values='Count')
.fillna(0)
.astype(int)
.reset_index())
df
Out[45]:
2 0 goin it mary and are been boys catch catching ... on \
0 john 0 0 1 1 1 1 0 0 1 ... 0
1 mary 0 0 0 1 0 0 1 1 0 ... 1
2 tom 1 1 0 0 0 0 0 0 0 ... 0
2 the there tom tom up well with ya'll you
0 0 1 0 1 1 1 1 0 2
1 1 0 1 0 0 0 0 1 1
2 0 0 0 0 0 0 0 0 0
[3 rows x 31 columns]
推荐阅读
- go - 问 import undefined Go
- c - 将插件添加到 C 程序
- reactjs - Highcharts React 使用日期时间轴更新动画
- amazon-web-services - Docker 映像大小在 aws ecr 上更改
- javascript - 关于将 html 文件转换为 json 以用于 react-email-editor 的问题
- javascript - 在组件之间传递 props | 反应
- reactjs - 有什么方法可以使 React Material-UI 单选按钮成为必需
- botframework - 无法使用 Bot Framework SDK v4 在 MS Teams 中呈现自适应卡
- python - 如何使用 langid LanguageIdentifier 使用 set_languages
- oracle - 每年如何返回01交易号