我有一个数据,我使用数据透视表方法进行了数据透视,现在数据如下所示:
rule_id a b c
50211 8 0 0
50249 16 0 3
50378 0 2 0
50402 12 9 6
我已将'rule_id'设置为索引。现在,我将一列与其对应的列进行比较,并使用结果创建另一列。这个想法是,如果第一列的值不是0,第二列要与之比较的第二列的值为0,则应在新创建的列中更新100,但是如果情况相反,则'Null'应该更新。如果两个列都为0,则还应更新'Null'。如果最后一列的值为0,则应更新'Null',而不是0,则应更新100。但是,如果两列的值都不为0(例如数据的最后一行),则对a列和b列的比较应该像这样:
value_of_b/value_of_a *50 + 50
以及b和c列:
value_of_c/value_of_b *25 + 25
并且类似地,如果有更多列,则乘法和加法值应为12.5,依此类推。
除了最后的结果(除法和乘法)外,我能够实现上述所有目的。我使用了这段代码:
m = df.eq(df.shift(-1, axis=1))
arr = np.select([df ==0, m], [np.nan, df], 1*100)
df2 = pd.DataFrame(arr, index=df.index).rename(columns=lambda x: f'comp{x+1}')
df3 = df.join(df2)
df是存储我一开始提到的数据透视表数据的数据框。使用此代码后,我的数据如下所示:
rule_id a b c comp1 comp2 comp3
50211 8 0 0 100 NaN NaN
50249 16 0 3 100 NaN 100
50378 0 2 0 NaN 100 NaN
50402 12 9 6 100 100 100
但是我希望数据看起来像这样:
rule_id a b c comp1 comp2 comp3
50211 8 0 0 100 NaN NaN
50249 16 0 3 100 NaN 100
50378 0 2 0 NaN 100 NaN
50402 12 9 6 87.5 41.67 100
如果你们能帮助我获得所需的数据,我将不胜感激。
编辑: 这是我的数据的样子:
答案 0 :(得分:1)
问题在于,在构建新的compx
列时使用的系数不仅取决于列的位置。实际上,在每一行中,它将在每个0值之后重置为其最大值50,并且是非0值之后的前一个值的一半。那些 resetable 系列很难在大熊猫中矢量化,尤其是在行中。在这里,我将构建一个仅包含那些系数的伴随数据框,并直接使用numpy基础数组来尽可能高效地计算它们。代码可能是:
# transpose the dataframe to process columns instead of rows
coeff = df.T
# compute the coefficients
for name, s in coeff.items():
top = 100 # start at 100
r = []
for i, v in enumerate(s):
if v == 0: # reset to 100 on a 0 value
top=100
else:
top = top/2 # else half the previous value
r.append(top)
coeff.loc[:, name] = r # set the whole column in one operation
# transpose back to have a companion dataframe for df
coeff = coeff.T
# build a new column from 2 consecutive ones, using the coeff dataframe
def build_comp(col1, col2, i):
df['comp{}'.format(i)] = np.where(df[col1] == 0, np.nan,
np.where(df[col2] == 0, 100,
df[col2]/df[col1]*coeff[col1]
+coeff[col1]))
old = df.columns[0] # store name of first column
# Ok, enumerate all the columns (except first one)
for i, col in enumerate(df.columns[1:], 1):
build_comp(old, col, i)
old = col # keep current column name for next iteration
# special processing for last comp column
df['comp{}'.format(i+1)] = np.where(df[col] == 0, np.nan, 100)
使用此初始数据框:
date 2019-04-25 15:08:23 2019-04-25 16:14:14 2019-04-25 16:29:05 2019-04-25 16:36:32
rule_id
50402 0 0 9 0
51121 0 1 0 0
51147 0 1 0 0
51183 2 0 0 0
51283 0 12 9 6
51684 0 1 0 0
52035 0 4 3 2
它给出了预期的结果:
date 2019-04-25 15:08:23 2019-04-25 16:14:14 2019-04-25 16:29:05 2019-04-25 16:36:32 comp1 comp2 comp3 comp4
rule_id
50402 0 0 9 0 NaN NaN 100.000000 NaN
51121 0 1 0 0 NaN 100.0 NaN NaN
51147 0 1 0 0 NaN 100.0 NaN NaN
51183 2 0 0 0 100.0 NaN NaN NaN
51283 0 12 9 6 NaN 87.5 41.666667 100.0
51684 0 1 0 0 NaN 100.0 NaN NaN
52035 0 4 3 2 NaN 87.5 41.666667 100.0
答案 1 :(得分:0)
好吧,我认为您可以遍历数据帧List
并使用if-else获得所需的输出。
df