Pandas Dataframe/Series - 将字符添加到字符串值

Posted

技术标签:

【中文标题】Pandas Dataframe/Series - 将字符添加到字符串值【英文标题】:Pandas Dataframe/Series - Adding character to string values 【发布时间】:2022-01-23 18:01:27 【问题描述】:

我正在寻求有关以下问题的帮助。

我有一个数据框:

df = pd.DataFrame(
                   'ID1': ['blabla-012345-blabla', 'blabla-012345-blabla', 'blabla-012345-blabla', 'blabla-012345-blabla', 'blabla-1234567891-blabla', 'blabla-123456-blabla', 'blabla-0123456789-blabla', 'blabla-0123456789-blabla', 'blabla-0123456789-blabla'],
                   'ID2': ['blabla-012345-blabla', 'blabla-123456-blabla', 'blabla-0123456789-blabla', 'blabla-1234567891-blabla', 'blabla-012345-blabla', 'blabla-0123456789-blabla', 'blabla-123456-blabla', 'blabla-0123456789-blabla', 'blabla-1234567891-blabla'],
                   'ID3': ['1234512345', '12345123456', '12345123456789', '123451234567891', '123451234567891', '123456123456789', '123456123456789', '123456789123456789', '1234567891234567891'],
                   'case': ['10', '11', '14', '15a_1', '15a_2', '15b_1', '15b_2', '18', '19']
                 )
df


    ID1                         ID2                         ID3                 case
0   blabla-012345-blabla        blabla-012345-blabla        1234512345          10
1   blabla-012345-blabla        blabla-123456-blabla        12345123456         11
2   blabla-012345-blabla        blabla-0123456789-blabla    12345123456789      14
3   blabla-012345-blabla        blabla-1234567891-blabla    123451234567891     15a_1
4   blabla-1234567891-blabla    blabla-012345-blabla        123451234567891     15a_2
5   blabla-123456-blabla        blabla-0123456789-blabla    123456123456789     15b_1
6   blabla-0123456789-blabla    blabla-123456-blabla        123456123456789     15b_2
7   blabla-0123456789-blabla    blabla-0123456789-blabla    123456789123456789  18
8   blabla-0123456789-blabla    blabla-1234567891-blabla    1234567891234567891 19

所有值都是字符串,但我的数据在导入 pandas 之前被认为是整数。

'blabla' 可以被认为是任何东西(不是随机的,但知道解决这个问题是无用的),它们使从 ID1 和 ID2 重建 ID3 的方式复杂化。

这就是我想从自身重建 ID3 的原因。

原来的 ID3 应该是: 'ID3' = 'ID1number'+'ID2number' 如果 ID1number

但正如我所说,ID 在导入之前被认为是整数,所以 ID1 和 ID2 中以数字开头的“0”刚刚消失。

我想重建 ID3 以填充缺失的“0”。 所以我做了这些掩码,并尝试更改与它们对应的值:

mask_ok = df['ID3'].str.contains('^(\d12|\d16|\d20)$')

mask_10_18 = df['ID3'].str.contains('^(\d10|\d18)$')

mask_11_19 = df['ID3'].str.contains('^(\d11|\d19)$')

mask_14 = df['ID3'].str.contains('^\d14$')

mask_15a = ((df['ID3'].str.contains('^\d15$'))
            &
            (df['ID1'].str.startswith('^blabla-0\d5-')
             |
             df['ID2'].str.startswith('^blabla-0\d5-')))

mask_15b = ((df['ID3'].str.contains('^\d15$'))
            &
            ~(df['ID1'].str.startswith('^blabla-0\d5-')
              |
              df['ID2'].str.startswith('^blabla-0\d5-')))

df.loc[mask_10_18] = '0'+df.loc[mask_10_18][:len(df.loc[mask_10_18])/2]+'0'+df.loc[mask_10_18][len(df.loc[mask_10_18])/2:]

df.loc[mask_14] = '0'+df.loc[mask_14][:5]+'0'+df.loc[mask_14][5:]

df.loc[mask_11_19|mask_15a] = '0'+df.loc[mask_11_19|mask_15a]

df.loc[mask_15b] = df.loc[mask_15b][:6]+'0'+df.loc[mask_15b][6:]

df[~mask_ok]

我想要的是所有零都放置得很好,以便数据框看起来像这样:

df = pd.DataFrame(
                   'ID1': ['blabla-012345-blabla', 'blabla-012345-blabla', 'blabla-012345-blabla', 'blabla-012345-blabla', 'blabla-1234567891-blabla', 'blabla-123456-blabla', 'blabla-0123456789-blabla', 'blabla-0123456789-blabla', 'blabla-0123456789-blabla'],
                   'ID2': ['blabla-012345-blabla', 'blabla-123456-blabla', 'blabla-0123456789-blabla', 'blabla-1234567891-blabla', 'blabla-012345-blabla', 'blabla-0123456789-blabla', 'blabla-123456-blabla', 'blabla-0123456789-blabla', 'blabla-1234567891-blabla'],
                   'ID3': ['012345012345', '012345123456', '0123450123456789', '0123451234567891', '0123451234567891', '1234560123456789', '1234560123456789', '01234567890123456789', '01234567891234567891'],
                   'case': ['12', '12', '16', '16', '16', '16', '16', '20', '20']
                 )
df

    ID1                         ID2                         ID3          case
0   blabla-012345-blabla        blabla-012345-blabla        012345012345            12
1   blabla-012345-blabla        blabla-123456-blabla        012345123456            12
2   blabla-012345-blabla        blabla-0123456789-blabla    0123450123456789        16
3   blabla-012345-blabla        blabla-1234567891-blabla    0123451234567891        16
4   blabla-1234567891-blabla    blabla-012345-blabla        0123451234567891        16
5   blabla-123456-blabla        blabla-0123456789-blabla    1234560123456789        16
6   blabla-0123456789-blabla    blabla-123456-blabla        1234560123456789        16
7   blabla-0123456789-blabla    blabla-0123456789-blabla    01234567890123456789    20
8   blabla-0123456789-blabla    blabla-1234567891-blabla    01234567891234567891    20

列案例只是在这里显示 ID3 中的位数,但它不在我的原始数据框中,我只是把它放在那里以提高可视化效果。你可以去掉它进行计算。

我在运行代码时遇到了这个错误:

TypeError                                 Traceback (most recent call last)
<ipython-input-30-91bff8470cf6> in <module>
     19               df['ID2'].str.startswith('^blabla-0')))
     20 
---> 21 df.loc[mask_10_18] = '0'+df.loc[mask_10_18][:len(df.loc[mask_10_18])/2]+'0'+df.loc[mask_10_18][len(df.loc[mask_10_18])/2:]
     22 
     23 df.loc[mask_14] = '0'+df.loc[mask_14][:5]+'0'+df.loc[mask_14][5:]

~\Anaconda3\lib\site-packages\pandas\core\frame.py in __getitem__(self, key)
   2997 
   2998         # Do we have a slicer (on rows)?
-> 2999         indexer = convert_to_index_sliceable(self, key)
   3000         if indexer is not None:
   3001             if isinstance(indexer, np.ndarray):

~\Anaconda3\lib\site-packages\pandas\core\indexing.py in convert_to_index_sliceable(obj, key)
   2208     idx = obj.index
   2209     if isinstance(key, slice):
-> 2210         return idx._convert_slice_indexer(key, kind="getitem")
   2211 
   2212     elif isinstance(key, str):

~\Anaconda3\lib\site-packages\pandas\core\indexes\base.py in _convert_slice_indexer(self, key, kind)
   3355             if self.is_integer() or is_index_slice:
   3356                 self._validate_indexer("slice", key.start, "getitem")
-> 3357                 self._validate_indexer("slice", key.stop, "getitem")
   3358                 self._validate_indexer("slice", key.step, "getitem")
   3359                 return key

~\Anaconda3\lib\site-packages\pandas\core\indexes\base.py in _validate_indexer(self, form, key, kind)
   5307             pass
   5308         else:
-> 5309             raise self._invalid_indexer(form, key)
   5310 
   5311     def _maybe_cast_slice_bound(self, label, side: str_t, kind):

TypeError: cannot do slice indexing on Int64Index with these indexers [1.0] of type float

我认为这是因为 pandas 将我的字符串切片视为我的数据帧上的链式切片。

我还尝试将 .str 放在所有对字符串的调用之前(例如掩码中的 .str.contains),但它也不起作用。

我该怎么做呢?

【问题讨论】:

【参考方案1】:

在我的问题中,我是说从 ID1 和 ID2 重建 ID3 会因 blabla- 和 -blabla 而变得复杂。这是错误的,因为我可以从 ID1 和 ID2 中提取数字(甚至是特定位数)。

df = pd.DataFrame(
                   'ID1': ['blabla-012345-blabla', 'blabla-012345-blabla', 'blabla-012345-blabla', 'blabla-012345-blabla', 'blabla-1234567891-blabla', 'blabla-123456-blabla', 'blabla-0123456789-blabla', 'blabla-0123456789-blabla', 'blabla-0123456789-blabla'],
                   'ID2': ['blabla-012346-blabla', 'blabla-123456-blabla', 'blabla-0123456789-blabla', 'blabla-1234567891-blabla', 'blabla-012345-blabla', 'blabla-0123456789-blabla', 'blabla-123456-blabla', 'blabla-0123456799-blabla', 'blabla-1234567891-blabla'],
                   'ID3': ['1234512345', '12345123456', '12345123456789', '123451234567891', '123451234567891', '123456123456789', '123456123456789', '123456789123456789', '1234567891234567891'],
                   'case': ['10', '11', '14', '15a_1', '15a_2', '15b_1', '15b_2', '18', '19']
                 )
df['num_ID1'] = df['ID1'].str.extractall(r'(\d+)').droplevel('match')
df['num_ID2'] = df['ID2'].str.extractall(r'(\d+)').droplevel('match')
df.loc[df['num_ID1'].astype(int)<df['num_ID2'].astype(int), 'new_col'] = df['num_ID1'] + df['num_ID2']
df.loc[df['num_ID2'].astype(int)<df['num_ID1'].astype(int), 'new_col'] = df['num_ID2'] + df['num_ID1']
df

df1 = pd.DataFrame(
                   'ID1': ['blabla-012345-blabla', 'blabla-012345-blabla', 'blabla-012345-blabla', 'blabla-012345-blabla', 'blabla-1234567891-blabla', 'blabla-123456-blabla', 'blabla-0123456789-blabla', 'blabla-0123456789-blabla', 'blabla-0123456789-blabla'],
                   'ID2': ['blabla-012346-blabla', 'blabla-123456-blabla', 'blabla-0123456789-blabla', 'blabla-1234567891-blabla', 'blabla-012345-blabla', 'blabla-0123456789-blabla', 'blabla-123456-blabla', 'blabla-0123456799-blabla', 'blabla-1234567891-blabla'],
                   'ID3': ['012345012346', '012345123456', '0123450123456789', '0123451234567891', '0123451234567891', '1234560123456789', '1234560123456789', '01234567890123456799', '01234567891234567891'],
                   'case': ['10', '11', '14', '15a_1', '15a_2', '15b_1', '15b_2', '18', '19']
                 )
print(df1['ID3']==df['new_col'])

0    True
1    True
2    True
3    True
4    True
5    True
6    True
7    True
8    True
dtype: bool

实际上,它比尝试屏蔽所有情况并在条件下对每个 ID3 进行切片要简单。我现在应该注意“blabla”可能是随机的这一事实,因此我只需要提取一定长度的组即可。它会完成的。 在这个例子中,使用字符串提取比我更简单。

【讨论】:

以上是关于Pandas Dataframe/Series - 将字符添加到字符串值的主要内容,如果未能解决你的问题,请参考以下文章

利用Python进行数据分析:Pandas(Series+DataFrame)

Pandas Dataframe/Series - 将字符添加到字符串值

pandas笔记

pandas基本介绍

pandas模块学习笔记1--数据结构

pandas笔记