Конвертировать Pandas Dataframe со смешанными типами данных в формат LibSVM - PullRequest
0 голосов
/ 28 апреля 2020

У меня есть pandas фрейм данных с миллионом строк и 3 столбцами. Столбцы имеют 3 разных типа данных. NumberOfFollowers имеет числовой тип данных, UserName - категориальный тип данных, Embeddings - категориально-установленный тип.

df:

Index  NumberOfFollowers                  UserName                    Embeddings        Target Variable

0        15                                name1                      [0.5 0.3 0.2]       0
1        4                                 name2                      [0.4 0.2 0.4]       1
2        8                                 name3                      [0.5 0.5 0.0]       0
3        10                                name1                      [0.1 0.0 0.9]       0
...      ...                               ....                       ...                 ..

Я хотел бы преобразовать этот pandas фрейм данных во входной формат LibSVM.

Желаемый вывод:

0 0:15 4:1 1:0.5 2:0.3 3:0.2
1 0:4 5:1 1:0.4 2:0.2 3:0.4
0 0:8 6:1 1:0.5 2:0.5 3:0.0
0 0:10 4:1 1:0.1 2:0.0 3:0.9
...

Одно решение, которое я нашел, использовало:

https://scikit-learn.org/stable/modules/generated/sklearn.datasets.dump_svmlight_file.html

Он принимает входные данные как NumPy массив или разреженная матрица.

Имя пользователя имеет миллион уникальных значений, поэтому вызов pd.get_dummies для этого столбца и сохранение его в виде плотного массива NumPy не является решением и не помещается в память.

Итак, я знаю, что это может быть сделано с использованием разреженных матриц, но тогда я не знаю, как преобразовать вышеуказанные данные со смешанными типами данных в разреженную матрицу, а затем использовать sklearn.datasets. dump_svmlight_file. html.

На самом деле у меня много столбцов со смешанными типами данных, и мне нужно преобразовать их в формат libSVM. Но все столбцы относятся к одному из трех указанных выше типов.

Заранее благодарим за любые мысли о том, как решить вышеуказанную проблему.

1 Ответ

0 голосов
/ 08 мая 2020

Я сам написал функцию. Это работает, но очень медленно. Любое решение Faster приветствуется.

def construct_line(row, columns, dtypes, string_dict, file_obj, index, time1):

    if index % 1000000 == 0:
            print(str(time.time() - time1) +": "+ str(index))

    global categorical_index
    numerical_index = 0
    new_line = str(row[-1])+ " "
    for i in range(len(columns) - 1):
            value_at_i = row[i]
            dtype_at_i = dtypes[i]
            column_name_at_i = columns[i]

            if ((dtype_at_i == object) or (dtype_at_i == bool)): # Categorical Features
                    if (dtype_at_i == bool):
                            value_at_i =  bool_to_str(value_at_i)

                    value_to_be_found = column_name_at_i +"_"+ value_at_i

                    if value_to_be_found in string_dict:
                            indexed_value = string_dict[value_to_be_found]
                            new_line = new_line + str(indexed_value)+":1 "

                    else:
                            indexed_value = categorical_index
                            categorical_index = categorical_index + 1
                            new_line = new_line + str(indexed_value)+":1 "
                            string_dict[value_to_be_found] = indexed_value

            else: # Numerical Features
                    new_line = new_line + str(numerical_index) + ":" +str(value_at_i)+" "
                    numerical_index = numerical_index + 1
    file_obj.write(new_line+"\n")

cnames_numerical = list(train_df.select_dtypes(exclude=['object', 'bool']).columns)
categorical_index = len(cnames_numerical) - 1 # Categorical indices start from here.
string_dict = {}
f_train_df = open("train_df.csv", 'a')
print(len(train_df))
time1 = time.time()
train_df.apply(lambda x : construct_line(x, train_df.columns, train_df.dtypes, string_dict, f_train_df, x.name,\
                                         time1), axis = 1)
f_train_df.close()
print(len(test_df))
f_test_df = open("test_df.csv", 'a')
test_df.apply(lambda x : construct_line(x, test_df.columns, test_df.dtypes, string_dict, f_test_df, x.name,\
                                       time1), axis = 1)
f_test_df.close()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...