Pandas Dataframe/Series - 将字符添加到字符串值
Pandas Dataframe/Series - Adding character to string values
我正在寻求有关以下问题的帮助。
我有一个数据框:
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('^(\d{12}|\d{16}|\d{20})$')
mask_10_18 = df['ID3'].str.contains('^(\d{10}|\d{18})$')
mask_11_19 = df['ID3'].str.contains('^(\d{11}|\d{19})$')
mask_14 = df['ID3'].str.contains('^\d{14}$')
mask_15a = ((df['ID3'].str.contains('^\d{15}$'))
&
(df['ID1'].str.startswith('^blabla-0\d{5}-')
|
df['ID2'].str.startswith('^blabla-0\d{5}-')))
mask_15b = ((df['ID3'].str.contains('^\d{15}$'))
&
~(df['ID1'].str.startswith('^blabla-0\d{5}-')
|
df['ID2'].str.startswith('^blabla-0\d{5}-')))
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),但它也不起作用。
我该怎么做呢?
在我的问题中,我是说从 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' 可能是随机的这一事实,因此我只需要提取一定长度的组即可。它会完成的。
在这个例子中使用字符串提取比我更简单。
我正在寻求有关以下问题的帮助。
我有一个数据框:
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”。
所以我做了那些掩码来做,并尝试更改与它们对应的值: 我想要的是所有零都放置得很好,以便数据框看起来像这样: 列大小写在这里只是为了显示 ID3 中的位数,但它不在我的原始数据框中,我只是把它放在那里以提高可视化效果。你可以去掉它进行计算。 我在 运行 代码 : 我认为这是因为 pandas 正在将我的字符串切片视为数据帧上的链式切片。 我也尝试将 .str 放在所有对字符串的调用前面(如掩码中的 .str.contains),但它也不起作用。 我该怎么做呢?mask_ok = df['ID3'].str.contains('^(\d{12}|\d{16}|\d{20})$')
mask_10_18 = df['ID3'].str.contains('^(\d{10}|\d{18})$')
mask_11_19 = df['ID3'].str.contains('^(\d{11}|\d{19})$')
mask_14 = df['ID3'].str.contains('^\d{14}$')
mask_15a = ((df['ID3'].str.contains('^\d{15}$'))
&
(df['ID1'].str.startswith('^blabla-0\d{5}-')
|
df['ID2'].str.startswith('^blabla-0\d{5}-')))
mask_15b = ((df['ID3'].str.contains('^\d{15}$'))
&
~(df['ID1'].str.startswith('^blabla-0\d{5}-')
|
df['ID2'].str.startswith('^blabla-0\d{5}-')))
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
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
在我的问题中,我是说从 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' 可能是随机的这一事实,因此我只需要提取一定长度的组即可。它会完成的。 在这个例子中使用字符串提取比我更简单。