【发布时间】:2021-12-05 20:17:40
【问题描述】:
我有一个手动创建的数据框。我正在编写一个复制数据帧并将新数据帧连接到第一个数据帧末尾的代码。现在,我需要代码来查看包含字符串的“名称”数据框的列的每个值,如果字符串中有数字,则将该数字加 1。我需要将数字转换为 int这样我就可以创建一个函数来查看数据帧并自动将数据帧中的最大数字加 1。一个例子:
import pandas as pd
data = {'ID': [1,2,3,4],
'Name': ['BN #1', 'HHC', 'A comp', 'B Comp']}
df = pd.DataFrame(data)
df['SysNum'] = [int(re.search('(?<=#)\d', x)[0]) for x in df['Name'].values]
之后新的df看起来像
data2 = {'ID': [1,2,3,4,5,6,7,8],
'Name': ['BN #1', 'HHC', 'A comp', 'B Comp','BN #2', 'HHC', 'A comp', 'B Comp']}
当我运行它时,我收到一个“NoneType”对象不可下标错误。这是有道理的,因为只有 BN # 行有一个数字,并且 re.search 在不满足字符串参数时返回 None,但我不知道如何告诉 python 忽略其他行。
编辑 每个数据帧只有第一行会增加 1,所以如果有一种更简单的方法我不使用 re.search,那很好。我知道有几种方法可以做到这一点,但我希望能够始终查看 BN 的字符串值,并在每次运行代码时将其增加 1。
正则表达式编辑
df2['BaseName'] = [re.sub('\d', '', x) for x in df2['Name'].values]
df['BaseName'] = [re.sub('\d', '', x) for x in df['Name'].values]
df2['SysNum'] = [int(re.search('(?<=#)\d', x)[0]) for x in df2['Name'].values]
# df2['SysNum'] = df2['Name'].get(r'(?<=#)\d').astype(int)
# df['SysNum'] = [int(re.search('(?<=#)\d', x)[0]) for x in df['Name'].values]
df['SysNum'] = df['Name'].str.contains('(?<=#)\d').astype(int)
m = re.search(r'(?<=#)\d', df2['Name'].iloc[0])
if m:
df2['SysNum'] = int(m.group(0)) + 1
n = re.search(r'(?<=#)\d', df['Name'].iloc[0])
if n:
df['SysNum'] = int(n.group(1)) + 1
new_names = df2['BaseName'].unique()
maxes2 = np.zeros((len(new_names), ))
for j in range(len(new_names)):
un2 = new_names[j]
maxes2[j] = df['SysNum'].loc[df['BaseName'] == un2].max()
df2['SysNum'].loc[df2['BaseName'] == un2] = np.linspace(1, len(df2['SysNum'].loc[df2['BaseName'] == un2]), len(df2['SysNum'].loc[df2['BaseName'] == un2]))
df2['SysNum'].loc[df2['BaseName'] == un2] += maxes2[j]
newnames2 = [s + '%d' % num for s,num in zip(df2['BaseName'].loc[df2['BaseName'] == un2].values, df2['SysNum'].loc[df2['BaseName'] == un2].values)]
df2['Name'].loc[df2['BaseName'] == un2] = newnames2
我的这段代码适用于两个数据帧,编号符合我的要求。前两个对数据框中的所有行都有一个“Name-###”命名约定。这允许顶部注释掉的 re.search 行运行得很好。我正在处理的接下来的两个数据框就像我之前用 BN #1 提出的示例,其余名称没有数字。当我运行注释掉的 re.search 行时,代码尝试将 NoneTypes 转换为 int 并且它不能这样做。当我现在按原样运行代码时,紧跟名称的每一行都会放置一个新数字,但我需要它在带有 # 的行中添加一个新数字。所以我需要并且我正在努力的是一段代码,它查看数据帧,寻找#号,将#号后的数字变成一个int,一个寻找最大int然后加1的循环该数字,将该新数字添加到新数据框,将新数据框添加到旧数据框以获得更大的主列表。
【问题讨论】:
-
修复 NoneType 试试
df['SysNum'] = df['Name'].str.contains('(?<=#)\d').astype(int) -
我认为这很接近。如果为真则返回 1,否则返回 0。因此,当我到达 BN 2 和 3 等时,新的“SysNum”列中只显示了 1 个。
-
那么,对于
BN #1,SysNum 应该是2,对于BN #5,SysNum 应该是6? -
df['SysNum'] = df['Name'].str.extract(r'#(\d+)')怎么样?您想如何处理 NA 结果? -
我想我没有充分解释那部分。我真的不需要其他名字发生任何事情,它们都会保持不变。我从 BN 之后的数字创建整数的唯一原因是寻找最大值。所以这些其他值对于“SysNum”列来说并不重要。