首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如果列表中有多个元素不为零,则计算列表元素的差值

如果列表中有多个元素不为零,则计算列表元素的差值
EN

Stack Overflow用户
提问于 2019-11-20 19:14:03
回答 4查看 83关注 0票数 0

有一个如下所示的数据集:

代码语言:javascript
复制
Date       Item        A.unit       B.Unit    C.Unit      D.Unit   
10/11       A,D          5            0         0          12
11/11       A,B,C       10            10        5          0
12/11       A           20             0        0           0  

我想要输出列,这样只要列表中有一个以上的元素,它就会计算单位的差值,当存在单个元素时,它就会显示零。因此,输出将是:

代码语言:javascript
复制
Date       Item        A.unit       B.Unit    C.Unit      D.Unit          output
    10/11       A,D          5            0         0          12           5-12=-7 
    11/11       A,B,C       10            10        5          0            10-10-5=-5
    12/11       A           20             0        0           0            0--since only one element is there

谁能告诉我如何获得输出列。

EN

回答 4

Stack Overflow用户

发布于 2019-11-20 19:24:12

使用无检查Item列的解决方案-它对每个Unit列使用第一个非0值,并用值的总和减去,如果只有1个值,则设置0

代码语言:javascript
复制
#all columns without first and second
df1 = df.iloc[:, 2:].mask(lambda x: x==0)
#alternative
#all columns with Unit in column names
#df1 = df.filter(like='Unit').mask(lambda x: x==0)
first = df1.bfill(axis=1).iloc[:, 0]
df['output'] = np.where(df1.count(axis=1) == 1, 0, first - df1.sum(axis=1) + first)
print (df)
    Date   Item  A.Unit  B.Unit  C.Unit  D.Unit  output
0  10/11    A,D       5       0       0      12    -7.0
1  11/11  A,B,C      10      10       5       0    -5.0
2  12/11      A      20       0       0       0     0.0

具有按Item列匹配解决方案-将Item分解为行,如果只有一个值,则按-10倍增,最后聚合sumfirstjoin

代码语言:javascript
复制
df = df.assign(Item = df['Item'].str.split(',')).explode('Item').reset_index(drop=True)
df['new'] = df.lookup(df.index, df['Item'] + '.Unit')

df.loc[df.duplicated(subset=['Date']), 'new'] *=  -1
df.loc[~df.duplicated(subset=['Date'], keep=False), 'new'] =  0


d1 = dict.fromkeys(df.columns.difference(['Date','Item','new']), 'first')
fin = {**{'Item':','.join}, **d1, **{'new':'sum'}}
df = df.groupby('Date', as_index=False).agg(fin)

print (df)
    Date   Item  A.Unit  B.Unit  C.Unit  D.Unit  new
0  10/11    A,D       5       0       0      12   -7
1  11/11  A,B,C      10      10       5       0   -5
2  12/11      A      20       0       0       0    0
票数 0
EN

Stack Overflow用户

发布于 2019-11-20 19:25:14

这里有一个解决方案。第一步是创建一个在特定行上执行所需操作的函数:

代码语言:javascript
复制
from functool import reduce
def sum_function(x):
  if len(x[x != 0]) == 1:
    return 0
  else:
    return reduce(lambda a,b: a-b, x)

如果行中只有一个元素不为0,则返回0。如果有更多的元素,则将它们全部减去。下面是如何将该函数应用于每一行:

代码语言:javascript
复制
columns = ['A.unit', 'B.unit', 'C.unit', 'D.unit']
df.apply(lambda x: sum_function(x[columns]), axis=1)

结果是:

代码语言:javascript
复制
0   -7
1   -5
2    0

您可以将其添加为新列:

代码语言:javascript
复制
df['output'] = df.apply(lambda x: sum_function(x[columns]), axis=1)
票数 0
EN

Stack Overflow用户

发布于 2019-11-20 19:28:08

尝试:

代码语言:javascript
复制
def calc(row):
    out = row[np.argmax(np.array(row.tolist()) > 0)]
    for c in row.values[np.argmax(np.array(row.tolist()) > 0)+1:]:
        out -= c
    if out == row.sum():
        return 0
    else:
        return out

df['output'] = df.drop(['Date','Item'], axis=1).apply(calc, axis=1)

输出:

代码语言:javascript
复制
    Date   Item  A.unit  B.Unit  C.Unit  D.Unit  output
0  10/11    A,D       5       0       0      12      -7
1  11/11  A,B,C      10      10       5       0      -5
2  12/11      A      20       0       0       0       0
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/58953026

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档