根据其值为pandas dataFrame分配一个替代值

时间:2018-08-02 18:55:19

标签: python pandas dataframe element rows

我正在尝试为pandas dataFrame对象中的列分配替代值。分配备用值的条件是该元素现在的值为零。

这是我的代码段:

df = pd.DataFrame({'A': [0, 1, 2, 0, 0, 1, 1 ,0], 'B': [1, 2, 3, 4, 1, 2, 3, 4]})

for i, row in df.iterrows():
    if row['A'] == 0.0:
        df.iloc[i]['A'] = df.iloc[i-1]['A'] + df.iloc[i]['B'] - df.iloc[i-1]['B']

但是,事实证明,这些元素中的值保持为零!以上效果为零。

这是怎么回事?

3 个答案:

答案 0 :(得分:2)

下面的原始答案适用于某些输入,但并不完全正确。我用问题中的数据帧测试您的代码,我发现它可以工作,但不能保证它可以与所有数据帧一起工作。这是一个不起作用的示例:

df = pd.DataFrame(np.random.randn(6,4), index=list(range(0,12,2)), columns=['A', 'B', 'C', 'D'])

此数据帧将导致您的代码失败,因为索引不像算法期望的那样为0、1、2 ...,而是index=list(range(0,12,2))定义的0、2、4,...

这意味着迭代器返回的i的值也将是0、2、4 ...,因此,当您尝试使用i-1作为参数时,将会得到意外的结果到iloc

简而言之,当您使用for i, row in df.iterrows():遍历数据帧时,i会采用您遍历的维度的索引值,因为它们是在数据帧中定义的< / em>。确保您知道在循环内将其与偏移量一起使用时这些值是什么。


原始答案:

我无法弄清楚为什么您的代码不起作用,但是我可以验证一下它不起作用。这可能与在迭代数据帧时修改数据帧有关,因为您可以使用df.iloc[1]['A'] = 0.0在循环外毫无问题地设置值。

尝试改用DataFrame.at

for i, row in df.iterrows():
    if row['A'] == 0.0:
        df.at[i, 'A'] = df.iloc[i-1]['A'] + df.iloc[i]['B'] - df.iloc[i-1]['B']

这并不能说明df.iloc[i-1]返回数据帧的最后一行,因此请注意,当A列的第一个值为0.0时。

答案 1 :(得分:1)

那又怎么样:

dependencies {
        classpath 'com.android.tools.build:gradle:3.1.3'

    .....
        //other codes here
    }

NaN在那里,因为第一个元素之前没有元素

答案 2 :(得分:1)

您正在使用chained indexing,它与著名的SettingWithCopy警告有关。检查Tom Augspurger在modern pandas中的SettingWithCopy设置。

通常,不建议使用df['A']['B']= ...形式的分配。在那里使用loc acessor都没关系。

如果在代码中添加打印语句:

for i, row in df.iterrows():
    print(df)
    if row['A'] == 0.0:
        df.iloc[i]['A'] = df.iloc[i-1]['A'] + df.iloc[i]['B'] - df.iloc[i-1]['B']

您看到发生了奇怪的事情。仅当“ A”列的第一行为0时,才修改数据帧df

正如蜥蜴人Bill所指出的,您需要一个访问器。但是,请注意,Bill的方法具有提供基于标签的访问的缺点。当数据帧的索引不同时,这可能不是您想要的。那么更好的解决方案是使用loc

for i, row in df.iterrows():
    if row['A'] == 0.0:
        df.loc[df.index[i], 'A'] = df.iloc[i-1]['A'] + df.iloc[i]['B'] - df.iloc[i-1]['B']

或iloc

    for i, row in df.iterrows():
        if row['A'] == 0.0:
            df.iloc[i, df.columns.get_loc('A')] = df.iloc[i-1]['A'] + df.iloc[i]['B'] - df.iloc[i-1]['B']

假定索引在后一种情况下是唯一的。 请注意,设置值时会发生链接索引。

尽管这种方法行得通,但是-上面的引言-不鼓励!