提问人:Maze 提问时间:10/10/2023 最后编辑:OCaMaze 更新时间:10/11/2023 访问量:183
使用 .split() 和 .strip() 从 DataFrame 对象列中提取字符串
Extract strings from dataframe object column with .split() and .strip()
问:
我有一个超过 17000 行和一列的数据帧。在此列中,多个条目显示为一个长字符串,用 和 分隔。'merged_tstbr'
'ID'
';'
\n
下面是此列中单元格的示例:
XDX_AbCd_XY_2415;\
XDX_AbCd_XY_3335;\
XDX_AbCd_XY_3351;\
XDX_AbCd_XY_3354
我使用以下脚本检查“ID”列中的所有行,如果 ID 在my_list中,则将其添加到新列表“tstbr_anf”中:
my_list = ['XDX_AbCd_XY_3351', 'XDX_AbCd_XY_3335'] # (and so on, 250 elements in total)
for index, row in merged_tstbr.iterrows():
row_values = [value.strip() for value in row['ID'].split('\n')]
matching = [value for value in row_values if value in my_list]
tstbr_anf.extend(matching)
在 250 个元素中,有 6 个未显示在 中。txtbr_anf
我在 excel 的“ID”列中检查了它们的存在,它们在这里,但不知何故没有被添加到 .它们也存在于my_list中。txtbr_anf
造成这种情况的可能原因是什么。
如何使用 Pandas 在 Python 中在 DataFrame 的一列中搜索一列中的任何和所有值 另一个数据帧的后续
答:
我用来尝试重现您的问题的输入数据
- 它基于您发布的单元格的内容,
- 我添加了第二行,其中包含简单修改的数字。
my_list = ['XDX_AbCd_XY_3351', 'XDX_AbCd_XY_3335']
merged_tstbr = pd.DataFrame({'ID': ['XDX_AbCd_XY_2415;\nXDX_AbCd_XY_3335;\nXDX_AbCd_XY_3351;\nXDX_AbCd_XY_3354',
'XDX_AbCd_XY_1234;\nXDX_AbCd_XY_4565;\nXDX_AbCd_XY_3579;\nXDX_AbCd_XY_7592']})
输入数据帧中的每个单元格都包含一个字符串中的多个 ID:
ID
0 XDX_AbCd_XY_2415;\nXDX_AbCd_XY_3335;\nXDX_AbCd...
1 XDX_AbCd_XY_1234;\nXDX_AbCd_XY_4565;\nXDX_AbCd...
请确认这与你的输入匹配,否则提供数据帧构造函数。
问题:
你似乎认为这会删除分号,但事实并非如此,除非你强迫它这样做。您可以使用(在下面的代码中注释掉)来验证这一点:您正在测试成员资格,仍然有关于它们的分号:.strip()
print
row_values
['XDX_AbCd_XY_2415;', 'XDX_AbCd_XY_3335;', 'XDX_AbCd_XY_3351;', 'XDX_AbCd_XY_3354']
快速修复:
- 要么将其添加到 ,则不需要:
.split()
.strip()
for index, row in merged_tstbr.iterrows():
row_values = [value for value in row['ID'].split(';\n')]
#print(row_values)
matching = [value for value in row_values if value in my_list]
tstbr_anf.extend(matching)
- 或者强迫关心:
.strip()
row_values = [value.strip(';') for value in row['ID'].split('\n')]
两者都将输出为:tstbr_anf
['XDX_AbCd_XY_3335', 'XDX_AbCd_XY_3351']
现在为什么这个问题只出现在 6 个 ID 上,我们只能知道您何时提供更大的输入数据。可能是分号只存在于少数单元格中。
如果您的数据看起来与您上一个问题中的任何问题类似:如何使用 Pandas 在 Python 中搜索数据帧列中的任何和所有值,那么实际上并非所有 ID 都有分号,但它也可能是其他不需要的字符。
备选建议
下面的两步过程将提取这些 ID,并在列表中保留仅存在于my_list中的 ID。然后,您可以直接分配给 。tstbr_anf
- 清理 ID
- 生成列表列表,从该 DataFrame 列中按单元格生成一个子列表)
- 分号的计数可能并非在所有情况下都存在
L = merged_tstbr['ID'].str.split(pat = ';\n|\n', regex=True)
0 [XDX_AbCd_XY_2415, XDX_AbCd_XY_3335, XDX_AbCd_...
1 [XDX_AbCd_XY_1234, XDX_AbCd_XY_4565, XDX_AbCd_...
- 下一步同时执行两件事:
- 将“子列表列表”展平为一个简单的列表
- 并根据my_list进行筛选
my_set = set(my_list) # sets allow faster membership search
tstbr_anf = [item
for sublist in L
for item in sublist
if item in my_set]
最终输出:
['XDX_AbCd_XY_3335', 'XDX_AbCd_XY_3351']
正如你所看到的,我们已经去掉了中间列表,它是代码中每行迭代的临时产物。matching
引用
- 双重理解:如何从列表列表中制作一个平面列表?
- 成员资格测试性能:Python 集与列表
假设您想查找列表和系列中所有项的全局交集,我将使用交集和正则表达式拆分:set
my_list = ['XDX_AbCd_XY_3351', 'XDX_AbCd_XY_3335']
my_set = set(my_list)
out = my_set.intersection(merged_tstbr['ID'].str.split('[;\n]+').explode())
# or
out = my_set.intersection(set().union(*merged_tstbr['ID'].str.split('[;\n]+')))
输出示例:{'XDX_AbCd_XY_3335', 'XDX_AbCd_XY_3351'}
如果您想要每行的交集:
import re
my_set = set(my_list)
out = [my_set.intersection(re.split('[;\n]+', s)) for s in merged_tstbr['ID']]
对于新列:
merged_tstbr['new'] = [my_set.intersection(re.split('[;\n]+', s))
for s in merged_tstbr['ID']]
输出示例:
ID new
0 XDX_AbCd_XY_2415;\nXDX_AbCd_XY_3335;\nXDX_AbCd_XY_3351;\nXDX_AbCd_XY_3354 {XDX_AbCd_XY_3335, XDX_AbCd_XY_3351}
1 XDX_AbCd_XY_2416;\nXDX_AbCd_XY_3336;\nXDX_AbCd_XY_3351 {XDX_AbCd_XY_3351}
使用的输入:
merged_tstbr = pd.DataFrame({'ID': ['XDX_AbCd_XY_2415;\nXDX_AbCd_XY_3335;\nXDX_AbCd_XY_3351;\nXDX_AbCd_XY_3354',
'XDX_AbCd_XY_2416;\nXDX_AbCd_XY_3336;\nXDX_AbCd_XY_3351']})
评论
S = set(my_list)
S
str
s
s
S
s
my_set
上一个:折叠一种特殊的列表结构
下一个:如何创建变量?
评论
;
my_list