В следующем кадре данных я хотел бы правильно разделить «ресурс» серии на его различные компоненты, изначально разделенные символом «_»:
import pandas as pd
Data = {'resource':['MTUG1_ABO_DPP_1','MTUG1_ABO_DPP_2','MTUG1_ABO_DPP_3','MTUG1_ABO_DPP_4','MTUG1_ABO_DPP_5','MTUG1_ABO_DPU_1','MTUG1_ABO_DPU_2','MTUG1_ABO_DPU_3','MTUG1_ABO_UUB_VDU1_1','MTUG1_ABO_UUB_VDU1_2','MTUG1_ABO_UUB_VDU1_3','MTUG1_ABO_UUB_VDU2_1','MTUG1_ABO_UUB_VDU2_2']}
df = pd.DataFrame(Data, columns= ['resource'])
Результат, который я хочу:
Итак, MTUG1 -> становится содержимым нового столбца «Узел». DPP DPU UUB--> становится содержимым для нового столбца «Единица». Затем мне нужно создать еще одну новую серию «vm», где я объединяю строку в «Unit» со следующим номером (разделенным добавлением «_»), и если содержимое в «unit_num» является VDUx, мне нужно также объединить его с помощью пятая часть, vdu_num.
Но если я использую:
df['Node']=df['resource'].str.split("_").str.get(0)
df['Unit']=df['resource'].str.split("_").str.get(2)
unit_num=df['resource'].str.split("_").str.get(3)
vdu_num=df['resource'].str.split("_").str.get(4)
df['vm']=df['Unit'].str.cat(vm_num, sep = "_").str.cat(vdu_num, sep = "_")
df['vm'].unique()
Я получаю только компоненты VDU:
array([nan, 'UUB_VDU1_1', 'UUB_VDU1_2', 'UUB_VDU1_3', 'UUB_VDU2_1',
'UUB_VDU2_2'], dtype=object)
в то время как, чтобы увидеть оставшуюся часть, я должен удалить последнюю конкатенацию. Как бы вы решили это?
Кроме того, заголовок «не может правильно разделить строки в серии» вообще ни о чем нам не говорит. «разделить серию строк, разделенных '_', на переменное количество полей, заполнив отсутствующие поля».
Вы можете применить два случая отдельно, используя логическое индексирование, где вы проверяете, является ли vdu_num
NaN или нет.
df.loc[~vdu_num.isna(), 'vm']=df['Unit'].str.cat(unit_num, sep = "_").str.cat(vdu_num, sep = "_")
df.loc[vdu_num.isna(), 'vm']=df['Unit'].str.cat(unit_num, sep = "_")
производит
resource Node Unit unit_num vdu_num vm
-- -------------------- ------ ------ ---------- --------- ----------
0 MTUG1_ABO_DPP_1 MTUG1 DPP 1 nan DPP_1
1 MTUG1_ABO_DPP_2 MTUG1 DPP 2 nan DPP_2
2 MTUG1_ABO_DPP_3 MTUG1 DPP 3 nan DPP_3
3 MTUG1_ABO_DPP_4 MTUG1 DPP 4 nan DPP_4
4 MTUG1_ABO_DPP_5 MTUG1 DPP 5 nan DPP_5
5 MTUG1_ABO_DPU_1 MTUG1 DPU 1 nan DPU_1
6 MTUG1_ABO_DPU_2 MTUG1 DPU 2 nan DPU_2
7 MTUG1_ABO_DPU_3 MTUG1 DPU 3 nan DPU_3
8 MTUG1_ABO_UUB_VDU1_1 MTUG1 UUB VDU1 1 UUB_VDU1_1
9 MTUG1_ABO_UUB_VDU1_2 MTUG1 UUB VDU1 2 UUB_VDU1_2
10 MTUG1_ABO_UUB_VDU1_3 MTUG1 UUB VDU1 3 UUB_VDU1_3
11 MTUG1_ABO_UUB_VDU2_1 MTUG1 UUB VDU2 1 UUB_VDU2_1
12 MTUG1_ABO_UUB_VDU2_2 MTUG1 UUB VDU2 2 UUB_VDU2_2
Спасибо! Он работает отлично! Что означает этот символ ~?
Рад, что это помогло! Символ «~» в логическом индексировании означает «не». Таким образом, первая строка выбирает строки, в которых «vdu_num не равно NaN». Рассмотрите возможность принятия ответа в соответствии с рекомендациями stackoverflow.com/help/someone-answers
кажется, не соответствует желаемому результату.
@PierreD согласен - использовал код OP для случая, который действительно работал, что несколько не соответствовало предоставленному выводу.
Вы можете упростить свое разделение (сделать это один раз), а затем также использовать where
, чтобы взять unit_num
или vdu_num
в зависимости от того, что не равно нулю:
df2 = (
df['resource']
.str.split('_', expand=True)[[0, 2, 3, 4]]
.set_axis('Node Unit unit_num vdu_num'.split(), axis=1)
)
df2['vm'] = df2['Unit'].str.cat(
df2['unit_num'].where(df2['vdu_num'].isnull(), df2['vdu_num']), sep='_')
Или, если вы предпочитаете перезаписать оригинал df
:
df = pd.concat([
df['resource'],
df['resource']
.str.split('_', expand=True)[[0, 2, 3, 4]]
.set_axis('Node Unit unit_num vdu_num'.split(), axis=1)
], axis=1)
df['vm'] = df['Unit'].str.cat(
df['unit_num'].where(df['vdu_num'].isnull(), df['vdu_num']), sep='_')
Исправьте ошибку в коде: NameError: имя 'vm_num' не определено в строке 6.