Несколько значений в одном столбце панды DataFrame

У меня есть некоторые данные, которые я обрабатываю из XML в pandas DataFrame. Данные XML выглядят примерно так:

<tracks> <track name="trackname1" variants="1,2,3,4,5"> <variant var="1,2,3"> <leg time="21:23" route_id="5" stop_id="103" serial="1"/> <leg time="21:26" route_id="5" stop_id="17" serial="2"/> <leg time="21:30" route_id="5" stop_id="38" serial="3"/> <leg time="20:57" route_id="8" stop_id="101" serial="1"/> <leg time="21:01" route_id="8" stop_id="59" serial="2"/> ... </variant> <variant var="4,5"> ... more leg elements </variant> </track> <track name="trackname2" variants="1,2,3,4,5,6,7"> <variant var="1"> ... more leg elements </variant> <variant var="2,3,4,5,7"> ... more leg elements </variant> </track> </tracks> 

Я импортирую это в pandas, потому что мне нужно иметь возможность присоединиться к этим данным с другими DataFrames, и мне нужно иметь возможность запрашивать такие вещи, как: «получить все ноги варианта 1 для route_id 5».

Я пытаюсь понять, как это сделать в pandas DataFrame. Должен ли я сделать DataFrame, который будет выглядеть примерно так:

 track_name variants time route_id stop_id serial "trackname1" "1,2,3" "21:23" "5" "103" "1" "trackname1" "1,2,3" "21:26" "5" "17" "2" ... "trackname1" "4,5" "21:20" "5" "103" "1" ... "trackname2" "1" "20:59" "3" "45" "1" ... you get the point 

Если это так, то как бы я (эффективно) извлечь, например, «все строки для варианта 3 на route_id 5»? Обратите внимание, что это должно дать мне все строки, которые имеют 3 в списке столбцов вариантов, а не только строки, которые имеют только «3» в столбце вариантов.

Есть ли другой способ построения DataFrame, который упростит это? Должен ли я использовать что-то другое, кроме панд?

Предполагая, что у вас достаточно памяти, ваша задача будет более легко выполнена, если ваш DataFrame проведет один вариант для каждой строки:

 track_name variants time route_id stop_id serial "trackname1" 1 "21:23" 5 103 1 "trackname1" 2 "21:23" 5 103 1 "trackname1" 3 "21:23" 5 103 1 "trackname1" 1 "21:26" 5 17 2 "trackname1" 2 "21:26" 5 17 2 "trackname1" 3 "21:26" 5 17 2 ... "trackname1" 4 "21:20" 5 103 1 "trackname1" 5 "21:20" 5 103 1 ... "trackname2" 1 "20:59" 3 45 1 

Затем вы можете найти «все строки для варианта 3 на route_id 5 с

 df.loc[(df['variants']==3) & (df['route_id']==5)] 

Если вы упаковываете много вариантов в одну строку, например,

 "trackname1" "1,2,3" "21:23" "5" "103" "1" 

то вы можете найти такие строки, используя

 df.loc[(df['variants'].str.contains("3")) & (df['route_id']=="5")] 

предполагая, что варианты всегда однозначные. Если есть также 2-значные варианты, такие как «13» или «30», вам нужно будет передать более сложный шаблон регулярного выражения для str.contains .

В качестве альтернативы вы можете использовать apply для разделения каждого варианта на запятую:

 df['variants'].apply(lambda x: "3" in x.split(',')) 

но это очень неэффективно, так как теперь вы будете называть функцию Python один раз для каждой строки и выполнять разделение строк и тест для членства в списке по сравнению с векторизованным целочисленным сравнением.

Таким образом, чтобы избежать возможного сложного регулярного выражения или относительно медленного вызова для apply , я считаю, что лучше всего построить DataFrame с одним целым вариантом для каждой строки.