Мне нужно обработать результаты моделирования FEM, которые я загрузил в фрейм данных Polars, которые создают два Кадры данных:
Код: Выделить всё
nodes_df = pl.DataFrame(
{"node":[1,2,3,4,5,6,7,8,9,10],
"x":[4.5,-4.6, 3.8,-3.8, 2.1,-9.3, 1.5,-6.7, 0.0, 3.6],
"y":[9.8,-9.9, 8.2,-8.3, 4.6,-2.0, 1.4,-6.1, 0.0, 1.0],
"z":[0.0,0.0,8.8,8.8,1.2,1.2,5.5,5.5,5.5,0.0,]})
elements = [1, 2, 3]
elements_df = pl.DataFrame(
{
"element": elements,
"N_1": [1, 1, 1],
"N_2": [2, 2, 2],
"N_3": [3, 3, 3],
"N_4": [4, 4, 4],
"N_5": [5, 5, 5],
"N_6": [6, 6, 6],
"N_7": [7, 7, 7],
"N_8": [8, 8, 8],
"N_9": [9, 9, 9],
"N_10": [10, 10, 10],
}
)
[img]https: //i.sstatic.net/zUxP4.png[/img]
elements_dfсодержит определения для всех элементов, где столбцы N_{x} de id своих узлов (порядок узлов важен), поэтому каждый элемент всегда имеет 10 разных узлов. В nodes_df может быть больше столбцов с другими результатами моделирования, которые я обработаю позже. Идея состоит в том, чтобы передать результаты, хранящиеся в nodes_df, в центроид элемента.
В примере есть 10 (поддельных) узлов и 3 (равны поддельным) элемента, это просто выборочные данные в каждой строке будут разными. Где nodes_df имеет столбец «node» для представления идентификатора узла, а x,y,z — координаты узла. В elements_df есть столбец "element" для идентификатора и столбцы N_ для идентификаторов узлов. Во-первых, я не знаю, лучше или хуже эта схема, чем наличие одного столбца со списком узлов в одном столбце, учитывая производительность и простоту использования фрейма данных, у меня нет проблем изменить схему.
Но мне нужно сделать перекрестную ссылку на оба фрейма данных, чтобы выполнить несколько вычислений результатов. Для начала мне нужно вычислить центроид элемента.
Поскольку я новичок в dataframe, я сделал это, чтобы прояснить свою точку зрения, но я знаю, что это худший код DataFrame, который кто-либо может сделать. напишите:
Код: Выделить всё
def coords(nodes: list):
# get nodes coordinates for a node list
return (
nodes_df.filter(pl.col("node").is_in(nodes))
.select((pl.col(("x", "y", "z"))))
.mean()
)
def centroid(el_id: int):
# get the first four nodes ids for el with id = el_id
nodes = elements_df.filter(pl.col("element") == el_id).to_numpy()[0][:4]
return coords(nodes)
# loop over all elements and create new dataframe
# or maybe use this schema:
# _tmp = {"element": [], "x": [],"y": [],"z": []}
_tmp = {"element": [], "centroid": []}
for el in elements:
c = centroid(el).to_numpy()[0]
_tmp["element"].append(el)
_tmp["centroid"].append(c)
# _tmp["x"].append(c[0])
# _tmp["y"].append(c[1])
# _tmp["z"].append(c[2])
# concat dataframes to add the new "centroid" column
elements_df = pl.concat((elements_df, pl.DataFrame(_tmp)), how="align")
Код: Выделить всё
shape: (3, 12)
┌─────────┬─────┬─────┬─────┬───┬─────┬─────┬──────┬───────────────────────────┐
│ element ┆ N_1 ┆ N_2 ┆ N_3 ┆ … ┆ N_8 ┆ N_9 ┆ N_10 ┆ centroid │
│ --- ┆ --- ┆ --- ┆ --- ┆ ┆ --- ┆ --- ┆ --- ┆ --- │
│ i64 ┆ i64 ┆ i64 ┆ i64 ┆ ┆ i64 ┆ i64 ┆ i64 ┆ list[f64] │
╞═════════╪═════╪═════╪═════╪═══╪═════╪═════╪══════╪═══════════════════════════╡
│ 1 ┆ 1 ┆ 2 ┆ 3 ┆ … ┆ 8 ┆ 9 ┆ 10 ┆ [1.233333, 2.7, 2.933333] │
│ 2 ┆ 1 ┆ 2 ┆ 3 ┆ … ┆ 8 ┆ 9 ┆ 10 ┆ [1.233333, 2.7, 2.933333] │
│ 3 ┆ 1 ┆ 2 ┆ 3 ┆ … ┆ 8 ┆ 9 ┆ 10 ┆ [1.233333, 2.7, 2.933333] │
└─────────┴─────┴─────┴─────┴───┴─────┴─────┴──────┴───────────────────────────┘
Код: Выделить всё
┌─────────┬─────┬─────┬─────┬───┬──────┬──────────┬─────┬──────────┐
│ element ┆ N_1 ┆ N_2 ┆ N_3 ┆ … ┆ N_10 ┆ x ┆ y ┆ z │
│ --- ┆ --- ┆ --- ┆ --- ┆ ┆ --- ┆ --- ┆ --- ┆ --- │
│ i64 ┆ i64 ┆ i64 ┆ i64 ┆ ┆ i64 ┆ f64 ┆ f64 ┆ f64 │
╞═════════╪═════╪═════╪═════╪═══╪══════╪══════════╪═════╪══════════╡
│ 1 ┆ 1 ┆ 2 ┆ 3 ┆ … ┆ 10 ┆ 1.233333 ┆ 2.7 ┆ 2.933333 │
│ 2 ┆ 1 ┆ 2 ┆ 3 ┆ … ┆ 10 ┆ 1.233333 ┆ 2.7 ┆ 2.933333 │
│ 3 ┆ 1 ┆ 2 ┆ 3 ┆ … ┆ 10 ┆ 1.233333 ┆ 2.7 ┆ 2.933333 │
└─────────┴─────┴─────┴─────┴───┴──────┴──────────┴─────┴──────────┘
Подробнее здесь: https://stackoverflow.com/questions/778 ... dataframes