在pandas系列中映射块

3
我正在尝试将代码映射到块。 块由数字范围定义,例如AAA0-AAA9将包含代码AAA0,AAA1,AAA2等。 范围可能会变化,但可以在列表中定义。 我需要帮助将pandas数据框中的代码转换为它们各自的块。
请参见起始数据框示例:
d = {'ID': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 'Code': [
'AAA1', 'AAA2', 'AAA3', 'AAA4', 'AAA5', 'CCC2', 'AAA7', 'AAA9', 'BBB1', 'BBB2']}
df = pd.DataFrame(data=d)

请看以下所需的数据框示例(包含'AAA0-9'、'CCC5-9'和'BBB0-5'块):
d = {'ID': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 'Code': [
'AAA0-9', 'AAA0-9', 'AAA0-9', 'AAA0-9', 'AAA0-9', 'CCC5-9', 'AAA0-9', 'AAA0-9', 'BBB0-5', 'BBB0-5']}
 df = pd.DataFrame(data=d)

编辑:使用额外的代码。与上面的概念相同,但可能适用多个块。
d = {'ID': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 'Code': ['AAA1 AAA2 AAA3', 'AAA2', 'AAA3 AAA9', 'AAA4', 'AAA5', 'CCC2 CCC3', 'AAA7', 
'AAA9', 'BBB1', 'BBB2']}
df = pd.DataFrame(data=d)
2个回答

5

使用字典,通过字符串索引创建的前3个值,可以使用 map 方法。

d = {'AAA':'AAA0-9', 'CCC':'CCC5-9', 'BBB':'BBB0-5'}
#or generate dict from list
#L = ['AAA0-9', 'CCC5-9', 'BBB0-5']
#d = {x[:3]:x for x in L}

df['Code'] = df['Code'].str[:3].map(d)
print (df)
     Code  ID
0  AAA0-9   1
1  AAA0-9   2
2  AAA0-9   3
3  AAA0-9   4
4  AAA0-9   5
5  CCC5-9   6
6  AAA0-9   7
7  AAA0-9   8
8  BBB0-5   9
9  BBB0-5  10

详情:

print (df['Code'].str[:3])
0    AAA
1    AAA
2    AAA
3    AAA
4    AAA
5    CCC
6    AAA
7    AAA
8    BBB
9    BBB
Name: Code, dtype: object

编辑:

如果需要扩展值:

a = df.Code.str.split()
b = np.repeat(df.ID.values, a.str.len())
c = np.concatenate(a.values)

d = {'AAA':'AAA0-9', 'CCC':'CCC5-9', 'BBB':'BBB0-5'}
df = pd.DataFrame({'Code':c, 'ID':b})
print (df)
    Code  ID
0   AAA1   1
1   AAA2   1
2   AAA3   1
3   AAA2   2
4   AAA3   3
5   AAA9   3
6   AAA4   4
7   AAA5   5
8   CCC2   6
9   CCC3   6
10  AAA7   7
11  AAA9   8
12  BBB1   9
13  BBB2  10

df['Code'] = df['Code'].str[:3].map(d)
print (df)
      Code  ID
0   AAA0-9   1
1   AAA0-9   1
2   AAA0-9   1
3   AAA0-9   2
4   AAA0-9   3
5   AAA0-9   3
6   AAA0-9   4
7   AAA0-9   5
8   CCC5-9   6
9   CCC5-9   6
10  AAA0-9   7
11  AAA0-9   8
12  BBB0-5   9
13  BBB0-5  10

此外,如果不需要更改格式:
df = (df.set_index('ID')['Code']
       .str.split(expand=True)
       .stack()
       .str[:3]
       .map(d)
       .groupby(level=0)
       .apply(' '.join)
       .reset_index(name='Code'))
print (df)
   ID                  Code
0   1  AAA0-9 AAA0-9 AAA0-9
1   2                AAA0-9
2   3         AAA0-9 AAA0-9
3   4                AAA0-9
4   5                AAA0-9
5   6         CCC5-9 CCC5-9
6   7                AAA0-9
7   8                AAA0-9
8   9                BBB0-5
9  10                BBB0-5

编辑1:

如果需要按范围生成字典:

L = ['AAA0-9', 'CCC2-9', 'BBB0-5']
d = (pd.Series(L, index=L)
      .str.extract('(?P<a>\D+)(?P<b>\d)-(?P<c>\d+)', expand=True)
      .set_index('a', append=True)
      .astype(int)
      .apply(lambda x: pd.Series(range(x.b, x.c + 1)), axis=1)
      .stack()
      .astype(int)
      .astype(str)
      .reset_index(name='d')
      .assign(a=lambda x: x.a + x.d)
      .rename(columns={'level_0':'e'})
      .set_index('a')['e']
      .to_dict()
      )

print (d)

{'BBB1': 'BBB0-5', 'CCC6': 'CCC2-9', 'CCC2': 'CCC2-9', 
 'BBB4': 'BBB0-5', 'CCC5': 'CCC2-9', 'BBB2': 'BBB0-5', 
 'CCC4': 'CCC2-9', 'AAA4': 'AAA0-9', 'BBB0': 'BBB0-5', 
 'AAA9': 'AAA0-9', 'BBB3': 'BBB0-5', 'CCC3': 'CCC2-9',
 'AAA0': 'AAA0-9', 'AAA3': 'AAA0-9', 'CCC9': 'CCC2-9', 
 'AAA2': 'AAA0-9', 'BBB5': 'BBB0-5', 'AAA1': 'AAA0-9', 
 'CCC8': 'CCC2-9', 'CCC7': 'CCC2-9', 'AAA8': 'AAA0-9', 
 'AAA7': 'AAA0-9', 'AAA5': 'AAA0-9', 'AAA6': 'AAA0-9'}

 df['Code'] = df['Code'].map(d)

抱歉,我稍微错误地表达了这个问题。系列中可能有多个代码。我已经在上面添加了一个示例。 - shbfy
不确定是否理解,相同的解决方案不起作用? - jezrael
谢谢,这非常有帮助!真的很感激 :) - shbfy

1

容纳任意长度代码的简单方法:

df.Code.str.extract('(\D+)', expand=False)

0    AAA
1    AAA
2    AAA
3    AAA
4    AAA
5    CCC
6    AAA
7    AAA
8    BBB
9    BBB
Name: Code, dtype: object

你甚至可以方便地命名列。
df.Code.str.extract('(?P<Block>\D+)(?P<Num>\d+)', expand=True)

  Block Num
0   AAA   1
1   AAA   2
2   AAA   3
3   AAA   4
4   AAA   5
5   CCC   2
6   AAA   7
7   AAA   9
8   BBB   1
9   BBB   2

谢谢。是否可以分多个块来执行此操作?例如,如果在序列中有AAA0 AAA4 BBB9? - shbfy
如果我理解正确的话,应该可以按照我所描述的方式工作。如果不能,那么我就不理解这种情况。你应该编辑你的问题并添加它。 - piRSquared

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接