Как заменить значение в pandas?

#python #pandas #dataframe

#python #pandas #фрейм данных

Вопрос:

Пытаюсь сгруппировать 23 разных метки в предпоследнем столбце «KDDTest .csv» в четыре группы. Пожалуйста, обратите внимание, что я удалил последний столбец csv перед выполнением этого.

Я прочитал файл .csv с помощью

 df = pd.read_csv('KDDTrain .csv', header=None, names = col_names)
  

где

 col_names = ["duration","protocol_type","service","flag","src_bytes",
    "dst_bytes","land","wrong_fragment","urgent","hot","num_failed_logins",
    "logged_in","num_compromised","root_shell","su_attempted","num_root",
    "num_file_creations","num_shells","num_access_files","num_outbound_cmds",
    "is_host_login","is_guest_login","count","srv_count","serror_rate",
    "srv_serror_rate","rerror_rate","srv_rerror_rate","same_srv_rate",
    "diff_srv_rate","srv_diff_host_rate","dst_host_count","dst_host_srv_count",
    "dst_host_same_srv_rate","dst_host_diff_srv_rate","dst_host_same_src_port_rate",
    "dst_host_srv_diff_host_rate","dst_host_serror_rate","dst_host_srv_serror_rate",
    "dst_host_rerror_rate","dst_host_srv_rerror_rate","label"]
  

Если я распечатаю первые 5 строк фрейма данных, это будет результат (пожалуйста, обратите внимание на столбец ‘label’):

используя print(df.head(5))

    duration protocol_type  ... dst_host_srv_rerror_rate    label
0         0           tcp  ...                     0.00   normal
1         0           udp  ...                     0.00   normal
2         0           tcp  ...                     0.00  neptune
3         0           tcp  ...                     0.01   normal
4         0           tcp  ...                     0.00   normal
  

Я попробовал оба этих метода группировки на основе того, что я нашел в Интернете:

Способ 1:

 df.replace(to_replace = ['ipsweep.', 'portsweep.', 'nmap.', 'satan.'], value = 'probe', inplace = True)
df.replace(to_replace = ['ftp_write.', 'guess_passwd.', 'imap.', 'multihop.', 'phf.', 'spy.', 'warezclient.', 'warezmaster.'], value = 'r2l', inplace = True)
df.replace(to_replace = ['buffer_overflow.', 'loadmodule.', 'perl.', 'rootkit.'], value = 'u2r', inplace = True)
df.replace(to_replace = ['back.', 'land.' , 'neptune.', 'pod.', 'smurf.', 'teardrop.'], value = 'dos', inplace = True)
  

Способ 2:

 df['label'] = df['label'].replace(['ipsweep.', 'portsweep.', 'nmap.', 'satan.'], 'probe',regex=True)
df['label'] = df['label'].replace(['ftp_write.', 'guess_passwd.', 'imap.', 'multihop.', 'phf.', 'spy.', 'warezclient.', 'warezmaster.'], 'r2l',regex=True)
df['label'] = df['label'].replace(['buffer_overflow.', 'loadmodule.', 'perl.', 'rootkit.'], 'u2r',regex=True)
df['label'] = df['label'].replace(['back.', 'land.' , 'neptune.', 'pod.', 'smurf.', 'teardrop.'], 'dos',regex=True)
  

Тем не менее, это все еще результат печати первых 5 строк фрейма данных:

 After replacing, first 5 rows of df: 

   duration protocol_type  ... dst_host_srv_rerror_rate    label
0         0           tcp  ...                     0.00   normal
1         0           udp  ...                     0.00   normal
2         0           tcp  ...                     0.00  neptune
3         0           tcp  ...                     0.01   normal
4         0           tcp  ...                     0.00   normal
  

Я ожидаю, что столбец label в строке 2 будет читать ‘dos’ вместо ‘neptune’, но этого не происходит.

Что я делаю не так? Приветствуется любая помощь.

Ответ №1:

Используя "neptune." в качестве to_replace значения с regex = True , вы указываете Pandas искать "neptune" и любой дополнительный символ (например, «neptuneX» или «neptune!»). Поскольку этот дополнительный символ отсутствует, вся фраза не заменяется. Вместо этого вы могли бы использовать просто "neptune" , или "neptune.?" для 0 или 1 дополнительных символов, или "neptune.*" для 0 или любого большего количества дополнительных символов.

Без regex = True вы говорите Pandas искать буквальную "neptune." фразу.

Ответ №2:

Может быть, вы используете "neptune." вместо "neptune"

Мои тесты, похоже, работают с "neptune"

 >>> df
     label
0  neptune
>>> df["label"].replace(["neptune."], "normal", regex=True)
0    neptune
Name: label, dtype: object
>>> df["label"].replace(["neptune"], "normal", regex=True)
0    normal
Name: label, dtype: object
>>> df["label"].replace(["neptune"], "normal")
0    normal
Name: label, dtype: object
  

Комментарии:

1. Это сработало, но я не знаю почему. В любом случае, большое вам спасибо!