极坐标中的行更新

问题描述 投票:0回答:3

假设我有这个数据框:

>>> polars.DataFrame([[1,2,3],[4,5,6],[7,8,9]],list('abc'))
shape: (3, 3)
┌─────┬─────┬─────┐
│ a   ┆ b   ┆ c   │
│ --- ┆ --- ┆ --- │
│ i64 ┆ i64 ┆ i64 │
╞═════╪═════╪═════╡
│ 1   ┆ 4   ┆ 7   │
│ 2   ┆ 5   ┆ 8   │
│ 3   ┆ 6   ┆ 9   │
└─────┴─────┴─────┘

请注意,下面我特别询问列“不重要”的情况 - 即我正在寻找一种解决方案,该解决方案不一定依赖于名为

a
b
c
的列或有一定数量的列。

我可以使用以下命令来更新某一行的某一列:

>>> polars.DataFrame([[1,2,3],[4,5,6],[7,8,9]],list('abc')).with_row_count().with_columns(a=polars.when(polars.col('row_nr') == 1).then(42).otherwise(polars.col('a'))).drop('row_nr')
shape: (3, 3)
┌─────┬─────┬─────┐
│ a   ┆ b   ┆ c   │
│ --- ┆ --- ┆ --- │
│ i64 ┆ i64 ┆ i64 │
╞═════╪═════╪═════╡
│ 1   ┆ 4   ┆ 7   │
│ 42  ┆ 5   ┆ 8   │
│ 3   ┆ 6   ┆ 9   │
└─────┴─────┴─────┘

但是如果我不知道我应该更新的话那就有点困难了

a

我该如何执行以下操作:

  1. 更换整行 - 例如我想用
    43,42,41
    替换第二行:
┌─────┬─────┬─────┐
│ a   ┆ b   ┆ c   │
│ --- ┆ --- ┆ --- │
│ i64 ┆ i64 ┆ i64 │
╞═════╪═════╪═════╡
│ 1   ┆ 4   ┆ 7   │
│ 43  ┆ 42  ┆ 41  │
│ 3   ┆ 6   ┆ 9   │
└─────┴─────┴─────┘
  1. 按条件替换特定行中的任何列 - 例如我想否定第二行中的任何值
    > 4
┌─────┬─────┬─────┐
│ a   ┆ b   ┆ c   │
│ --- ┆ --- ┆ --- │
│ i64 ┆ i64 ┆ i64 │
╞═════╪═════╪═════╡
│ 1   ┆ 4   ┆ 7   │
│ 2   ┆ -5  ┆ -8  │
│ 3   ┆ 6   ┆ 9   │
└─────┴─────┴─────┘
python python-polars
3个回答
4
投票

pl.all
可以用作
when
表达式中每一列(即每个元素)的简写。
cumcount
可以延迟复制行索引,无需任何
with_row_count
列。将所有内容放在一起,作为第 2 部分:

df.with_columns(
    pl.when((pl.all().cumcount() == 1) & (pl.all() > 4))
    .then(-pl.all())
    .otherwise(pl.all())
    .keep_name()
)

除了将

df
暂时设为一列之外,我不确定第 1 部分是否有更好的方法,请执行与上面类似的方法,然后取消嵌套:

df.select(x=pl.concat_list(pl.all())).select(
    x=pl.when(pl.col("x").cumcount() == 1)
    .then([43, 42, 41])
    .otherwise(pl.col("x"))
    .arr.to_struct(fields=df.columns)
).unnest("x")

2
投票

只需使用生成器/列表理解。

df.select(
    (pl.when(pl.first().cumcount()==1)
        .then(pl.lit(x))
        .otherwise(pl.col(df.columns[i])))
        .alias(df.columns[i]) for i, x in enumerate([43,42,41])
)

这种方法的问题在于它依赖于

df.columns
,所以你不能把它放在链的末尾。但是,如果将其放入函数中并将其猴子修补到 DataFrame 命名空间中,则可以解决这个问题。只需将所有对
df
的引用更改为 self,如下所示:

def replace_row(self, row_index, new_values):
    return self.select(
    (pl.when(pl.first().cumcount()==row_index)
        .then(pl.lit(x))
        .otherwise(pl.col(self.columns[i])))
        .alias(self.columns[i]) for i, x in enumerate(new_values)
)
pl.DataFrame.replace_row=replace_row
del replace_row

现在你可以像这样链接:

df.with_columns(d=pl.Series([2,8,1])).replace_row(0, [1,2,3,4])

shape: (3, 4)
┌─────┬─────┬─────┬─────┐
│ a   ┆ b   ┆ c   ┆ d   │
│ --- ┆ --- ┆ --- ┆ --- │
│ i64 ┆ i64 ┆ i64 ┆ i64 │
╞═════╪═════╪═════╪═════╡
│ 1   ┆ 2   ┆ 3   ┆ 4   │
│ 2   ┆ 5   ┆ 8   ┆ 8   │
│ 3   ┆ 6   ┆ 9   ┆ 1   │
└─────┴─────┴─────┴─────┘

您还可以注册自己的命名空间,如所示,但该方法的语法将是

df.mynamespace.replace_row()

我更喜欢将其放在 df 级别。如果您要创建很多这样的辅助函数,那么将它们全部放在自己的命名空间中可能是有意义的。


0
投票

如果需要更新给定索引处的行,可以使用

pl.DataFrame.update

# ensure df has index column
df = df.with_row_index()

# create dataframe for row
row = pl.DataFrame(data=[[2, 41, 42, 43]], schema=df.schema, orient="row")

# update df
df.update(row, on="index")
shape: (3, 4)
┌───────┬─────┬─────┬─────┐
│ index ┆ a   ┆ b   ┆ c   │
│ ---   ┆ --- ┆ --- ┆ --- │
│ u32   ┆ i64 ┆ i64 ┆ i64 │
╞═══════╪═════╪═════╪═════╡
│ 0     ┆ 1   ┆ 4   ┆ 7   │
│ 1     ┆ 2   ┆ 5   ┆ 8   │
│ 2     ┆ 41  ┆ 42  ┆ 43  │
└───────┴─────┴─────┴─────┘

请注意,传递给

data
pl.DataFrame
参数的列表中的第一个值是应更新的行的索引。

© www.soinside.com 2019 - 2024. All rights reserved.