多部分操作 post str.split() Pandas
Multi-part manipulation post str.split() Pandas
我有一个数据子集(单列),我们称之为 ID:
ID
0 07-1401469
1 07-89556629
2 07-12187595
3 07-381962
4 07-99999085
当前格式是(通常)YY-[最多 8 个字符的 ID]。
期望的输出格式是更统一的 YYYY-xxxxxxxx:
ID
0 2007-01401469
1 2007-89556629
2 2007-12187595
3 2007-00381962
4 2007-99999085
知道以前做过padding,思路就是结合
df['id'].str.split('-').str[0].apply(lambda x: '{0:20>4}'.format(x))
df['id'].str.split('-').str[1].apply(lambda x: '{0:0>8}'.format(x))
不过我运行遇到了几个问题:
- “{0:20>4}”中的“20”必须是单数而不是字符串
- 尝试执行类似下面的操作只会导致 df['id'] 获取最后一个 lambda 的属性并尝试以任何其他方式组合多个 apply/lambdas 只是行不通。我开始沿着垫 left/right 路线走,但那似乎是倒退的。
df['id'] = (df['id'].str.split('-').str[0].apply(lambda x: '{0:X>4}'.format(x)).str[1].apply(lambda x: '{0:0>8}'.format(x)))
我目前的解决方案(但讨厌,因为它又长又乱,而且在我看来不干净)是:
df['idyear'] = df['id'].str.split('-').str[0].apply(lambda x: '{:X>4}'.format(x)) # Split on '-' and pad with X
df['idyear'] = df['idyear'].str.replace('XX', '20') # Replace XX with 20 to conform to YYYY
df['idnum'] = df['id'].str.split('-').str[1].apply(lambda x: '{0:0>8}'.format(x)) # Pad 0s up to 8 digits
df['id'] = df['idyear'].map(str) + "-" + df['idnum'] # Merge idyear and idnum to remake id
del df['idnum'] # delete extra
del df['idyear'] # delete extra
哪个有效
ID
0 2007-01401469
1 2007-89556629
2 2007-12187595
3 2007-00381962
4 2007-99999085
但我的问题是
- 有没有办法在一行中 运行 多个 apply() 函数,这样我就不会创建临时变量
- 有没有比用 'XX' 替换 '20'
更好的方法
我觉得整个代码块可以压缩到 1 或 2 行,我只是不知道如何压缩。到目前为止,我在 SO 和 Pandas 上看到的关于 highlights/relates 到单一操作的所有内容。
一个选择是拆分;然后使用 str.zfill
填充 '0'
s。还要在拆分前添加 '20'
s,因为无论如何你似乎都需要它:
tmp = df['ID'].radd('20').str.split('-')
df['ID'] = tmp.str[0] + '-'+ tmp.str[1].str.zfill(8)
输出:
ID
0 2007-01401469
1 2007-89556629
2 2007-12187595
3 2007-00381962
4 2007-99999085
我会分两步完成,使用 .str.replace
:
df["ID"] = df["ID"].str.replace(r"^(\d{2})-", r"20-", regex=True)
df["ID"] = df["ID"].str.replace(r"-(\d+)", lambda g: f"-{g[1]:0>8}", regex=True)
print(df)
打印:
ID
0 2007-01401469
1 2007-89556629
2 2007-12187595
3 2007-00381962
4 2007-99999085
我有一个数据子集(单列),我们称之为 ID:
ID
0 07-1401469
1 07-89556629
2 07-12187595
3 07-381962
4 07-99999085
当前格式是(通常)YY-[最多 8 个字符的 ID]。 期望的输出格式是更统一的 YYYY-xxxxxxxx:
ID
0 2007-01401469
1 2007-89556629
2 2007-12187595
3 2007-00381962
4 2007-99999085
知道以前做过padding,思路就是结合
df['id'].str.split('-').str[0].apply(lambda x: '{0:20>4}'.format(x))
df['id'].str.split('-').str[1].apply(lambda x: '{0:0>8}'.format(x))
不过我运行遇到了几个问题:
- “{0:20>4}”中的“20”必须是单数而不是字符串
- 尝试执行类似下面的操作只会导致 df['id'] 获取最后一个 lambda 的属性并尝试以任何其他方式组合多个 apply/lambdas 只是行不通。我开始沿着垫 left/right 路线走,但那似乎是倒退的。
df['id'] = (df['id'].str.split('-').str[0].apply(lambda x: '{0:X>4}'.format(x)).str[1].apply(lambda x: '{0:0>8}'.format(x)))
我目前的解决方案(但讨厌,因为它又长又乱,而且在我看来不干净)是:
df['idyear'] = df['id'].str.split('-').str[0].apply(lambda x: '{:X>4}'.format(x)) # Split on '-' and pad with X
df['idyear'] = df['idyear'].str.replace('XX', '20') # Replace XX with 20 to conform to YYYY
df['idnum'] = df['id'].str.split('-').str[1].apply(lambda x: '{0:0>8}'.format(x)) # Pad 0s up to 8 digits
df['id'] = df['idyear'].map(str) + "-" + df['idnum'] # Merge idyear and idnum to remake id
del df['idnum'] # delete extra
del df['idyear'] # delete extra
哪个有效
ID
0 2007-01401469
1 2007-89556629
2 2007-12187595
3 2007-00381962
4 2007-99999085
但我的问题是
- 有没有办法在一行中 运行 多个 apply() 函数,这样我就不会创建临时变量
- 有没有比用 'XX' 替换 '20' 更好的方法
我觉得整个代码块可以压缩到 1 或 2 行,我只是不知道如何压缩。到目前为止,我在 SO 和 Pandas 上看到的关于 highlights/relates 到单一操作的所有内容。
一个选择是拆分;然后使用 str.zfill
填充 '0'
s。还要在拆分前添加 '20'
s,因为无论如何你似乎都需要它:
tmp = df['ID'].radd('20').str.split('-')
df['ID'] = tmp.str[0] + '-'+ tmp.str[1].str.zfill(8)
输出:
ID
0 2007-01401469
1 2007-89556629
2 2007-12187595
3 2007-00381962
4 2007-99999085
我会分两步完成,使用 .str.replace
:
df["ID"] = df["ID"].str.replace(r"^(\d{2})-", r"20-", regex=True)
df["ID"] = df["ID"].str.replace(r"-(\d+)", lambda g: f"-{g[1]:0>8}", regex=True)
print(df)
打印:
ID
0 2007-01401469
1 2007-89556629
2 2007-12187595
3 2007-00381962
4 2007-99999085