【问题标题】:How to substitute values in a column in a dataframe based on its column name, values in another column and index range?如何根据列名、另一列中的值和索引范围替换数据框中列中的值?
【发布时间】:2021-12-04 12:46:36
【问题描述】:

我有一个具有这些特征的数据框(索引是浮点值):

import pandas as pd

d = {'A': [1,2,3,4,5,6,7,8,9,10],
     'B': [1,2,3,4,5,6,7,8,9,10],
     'C': [1,2,3,4,5,6,7,8,9,10],
     'D': ['one','one','one','one','one','two','two','two','two','two']}

df = pd.DataFrame(data=d)
df
        A   B   C    D
50.0    1   1   1  one
50.2    2   2   2  one
50.4    3   3   3  one
50.6    4   4   4  one
50.8    5   5   5  one
51.0    6   6   6  two
51.2    7   7   7  two
51.4    8   8   8  two
51.6    9   9   9  two
51.8   10  10  10  two

以及具有这些值的偏移量列表(它们也是浮点数):

offsets = [[0.4, 0.6, 0.8], [0.2, 0.4, 0.6]]

我需要遍历 A、B 和 C 列上的数据框,从 D 列中选择分类值,根据与列表中偏移量相关的索引将 A、B 和 C 列中的最后一个值替换为 nan ,产生这样的数据框:

        A   B   C    D
50.0    1   1   1  one
50.2    2   2  nan one
50.4    3  nan nan one
50.6   nan nan nan one
50.8   nan nan nan one
51.0    6   6   6  two
51.2    7   7   7  two
51.4    8   8  nan two
51.6    9  nan nan two
51.8   nan nan nan two

offset的值是指什么值必须从下往上设置为nan。例如:offsets[0][0]=0.4,所以对于A列当D == 'one'时,自下而上的两个值必须设置为nan(第4行和第3行,50.8-0.4 = 50.4 - 50.4不变)。对于 A,当 D == 'two' 时,偏移量[1][0]=0.2,因此必须将自下而上的一个值设置为 nan(第 9 行,51.8-0.2 = 51.6 - 51.6 不变)。 Offsets[1][0]=0.6,所以对于B列当D == 'one'时,自下而上的三个值必须设置为nan(第4、3和2行,50.8-0.6 = 50.2 - 50.2不'不改变)。对于 B,当 D == 'two' 时,偏移量[1][1]=0.4,因此必须将自下而上的两个值设置为 nan(第 9 行和第 8 行,51.8-0.4 = 51.4 - 51.4 不变)。对于 C 列也是一样的。

知道怎么做吗?快速评论 - 我想替换数据框本身中的这些值,而不创建新值。

【问题讨论】:

  • 为什么第二行只有一个偏移量,第三行是两个偏移量?
  • 这里的偏移量是什么意思?
  • 抱歉,我没有说得那么具体。偏移量的值意味着什么值必须从下往上设置为 nan。例如:offsets[0]=2,所以对于列 A 当 D == 'one' 时,必须将自下而上的两个值设置为 nan(第 4 行和第 3 行)。对于 A 当 D == 'two' 时,必须将自下而上的两个值设置为 nan(第 9 行和第 8 行)。对于 offsets[1]=3,B 列也一样,以此类推。

标签: python pandas dataframe indexing substitution


【解决方案1】:

一种方法是使用apply 将每列的最后一个值设置为NaN:

import pandas as pd

# toy data
df = pd.DataFrame(data={'A': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
                        'B': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
                        'C': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
                        'D': ['one', 'one', 'one', 'one', 'one', 'two', 'two', 'two', 'two', 'two']})
offsets = [2, 3, 4]
offset_lookup = dict(zip(df.columns[:3], offsets))


def funny_shift(x, ofs=None):
    """This function shift each column by the given offset in the ofs parameter"""
    for column, offset in ofs.items():
        x.loc[x.index[-1 * offset:], column] = None
    return x


df.loc[:, ["A", "B", "C"]] = df.groupby("D").apply(funny_shift, ofs=offset_lookup)
print(df)

输出

     A    B    C    D
0  1.0  1.0  1.0  one
1  2.0  2.0  NaN  one
2  3.0  NaN  NaN  one
3  NaN  NaN  NaN  one
4  NaN  NaN  NaN  one
5  6.0  6.0  6.0  two
6  7.0  7.0  NaN  two
7  8.0  NaN  NaN  two
8  NaN  NaN  NaN  two
9  NaN  NaN  NaN  two

更新

如果每个组有多个更新,您可以这样做:

offsets = [[2, 3, 4], [1, 2, 3]]
offset_lookup = (dict(zip(df.columns[:3], offset)) for offset in offsets)


def funny_shift(x, ofs=None):
    """This function shift each column by the given offset in the ofs parameter"""
    current = next(ofs)
    for column, offset in current.items():
        x.loc[x.index[-1 * offset:], column] = None
    return x


df.loc[:, ["A", "B", "C"]] = df.groupby("D").apply(funny_shift, ofs=offset_lookup)
print(df)

【讨论】:

  • 再次抱歉,我忘记了 D 列中的值代表不同的偏移量集,因为它们可以有不同的值。我再次更改了问题以包含此问题。我现在不在电脑旁,我无法测试您的答案是否适用于这种不同的偏移结构。
  • @LucasOliveira 我们如何知道哪组偏移对应于 D 列中的每个值?
  • 它是连续的,因此与 D 列中第一个值相关联的第一行将始终与偏移量中的第一个列表(offsets[0])相关。
  • 我测试了您的脚本,它适用于合成数据框,但它不适用于我的真实数据......我认为这是因为我的索引和偏移量值是浮点数。
  • 是的,就是这样。我在这里简化了示例,但我的数据框中的索引实际上是深度测量值、浮点值。偏移量也是小数。所以你代码的 x.index[-1 * offset:] 部分对我不起作用。
猜你喜欢
  • 1970-01-01
  • 2021-06-29
  • 2021-06-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-02-14
  • 2021-01-05
  • 2020-04-05
相关资源
最近更新 更多