python-3.x - Python/Pandas 仅当值不为 0 时才进行减法

标签 python-3.x pandas dataframe subtraction

我从看起来像这样的数据开始,但有更多的行:

Location  Sample  a     b     c     d     e     f     g     h     i
1         w       14.6  0     0     0     0     0     0     0     16.8
2         x       0     13.6  0     0     0     0     0     0     16.5
3         y       0     0     15.5  0     0     0     0     0     16.9
4         z       0     0     0     0     14.3  0     0     0     15.7
...

数据按前两列索引。我需要从 a - h 中的每个值中减去 i 列中的值,并在每个原始列的数据框右侧添加一个新列。但是,如果第一列中有零,我希望它保持为零而不是相减。例如,如果我的代码有效,我会将以下列添加到右侧的数据框中

Location  Sample  ...  a2    b2    c2    d2    e2    f2    g2    h2 
1         w       ...  -2.2  0     0     0     0     0     0     0
2         x       ...  0     -2.9  0     0     0     0     0     0
3         y       ...  0     0     -1.4  0     0     0     0     0
4         z       ...  0     0     0     0     -1.4  0     0     0
...

如果当前列中的值不为零,我尝试使用 pandas 中的 where 来仅减去第 i 列中的值,使用以下代码:

import pandas as pd

normalizer = i
columns = list(df.columns.values)

for column in columns:
    if column == normalizer: continue
    newcol = gene + "2"
    df[newcol] = df.where(df[column] == 0, 
                df[column] - df[normalizer], axis = 0)

我使用 for 循环,因为列数并不总是相同,并且要减去的列将使用不同的数据集具有不同的名称。

我收到此错误:“ValueError:传递的项目数错误为 9,放置意味着 1”。

我认为减法导致了问题,但我不知道如何改变它以使其发挥作用。任何帮助将不胜感激。

提前致谢。

最佳答案

方法 1(相当快:大约比方法 2 快 3 倍)
1. 选择相关的列
2. 做减法
3. 使用减法之前构建的 0, 1 矩阵进行元素乘法。 (df_ref > 0) 中的每个元素如果最初为 0,则为 0,否则为 1。

ith_col = df["i"]
subdf = df.iloc[:, 2:-1]  # a - h columns 
df_temp = subdf.sub(ith_col, axis=0).multiply(subdf > 0).add(0)
df_temp.columns = ['a2', 'b2', 'c2', 'd2', 'e2', 'f2', 'g2', 'h2'] # rename columns
df_desired = pd.concat([df, df_temp], axis=1)

请注意,在此方法中,0 为负数。因此,最后我们有一个额外的 add(0) 。是的,0 可以是负数。 :P

方法2(更具可读性)
1.有条件查找大于0的部分。
2. 选择相关的行
3. 减法
4.填写0。

ith_col = df["i"]
df[df > 0].iloc[:,2:-1].sub(ith_col, axis=0).fillna(0)

第二种方法与@Wen的答案非常相似。归功于他:P

两种方法的速度比较(在Python 3和pandas 0.20上测试)

%timeit subdf.sub(ith_col, axis=0).multiply(subdf > 0).add(0)
688 µs ± 30.9 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
%timeit df[df > 0].iloc[:,2:-1].sub(ith_col, axis=0).fillna(0)
2.97 ms ± 248 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

引用:

DataFrame.multiply与另一个数据框执行元素乘法。

关于python-3.x - Python/Pandas 仅当值不为 0 时才进行减法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48053220/

相关文章:

python - 连接日期列

python - 如何用小时列融化 `pandas.DataFrame` 并将它们划分为 15 分钟间隔

python-3.x - 为 Pandas 中的每个组填充缺失的日期和回填值

python - 在 Python 中递增日期字符串 YYYY-MM-DD 的最快方法是什么?

python - 多级列表理解中是否需要中间列表

python - 在 Python 中连接成对的列表元素

python - 使用 QThread 和 pyqtSignal,为什么不同线程中的进程会卡住 GUI?

python - Pandas 随机用 NaN 替换值

python - pandas 获取某个大小范围内的行子集

R - 减少合并和超过 2 个后缀(或 : how to merge multiple dataframes and keep track of columns)