我有一个数据框,其中包含两列A
和B
,其中包含列表:
import pandas as pd
df = pd.DataFrame({"A" : [[1,5,10], [], [2], [1,2]],
"B" : [[15, 2], [], [6], []]})
我想构造第三列C
,该列的定义应等于A
和B
中的列表元素之间的最小可能差值(如果它们不是空的) ,如果其中一个或两个为空,则为0。
第一行的最小差异为1(我们取绝对值..),第二行由于列表为空而为0,第三行为4,第四行又由于一个空列表而为0,所以我们最终以:
df["C"] = [1, 0, 4, 0]
答案 0 :(得分:3)
这是不容易矢量化的,因为您有object
个dtype系列列表。您可以对itertools.product
使用列表推导:
from itertools import product
zipper = zip(df['A'], df['B'])
df['C'] = [min((abs(x - y) for x, y in product(*vals)), default=0) for vals in zipper]
# alternative:
# df['C'] = [min((abs(x - y) for x, y in product(*vals)), default=0) \
# for vals in df[['A', 'B']].values]
print(df)
# A B C
# 0 [1, 5, 10] [15, 2] 1
# 1 [] [] 0
# 2 [2] [6] 4
# 3 [1, 2] [] 0
答案 1 :(得分:2)
您可以使用以下列表推导,检查两列中笛卡尔积(itertools.product
)的min
差异
[min(abs(i-j) for i,j in product(*a)) if all(a) else 0 for a in df.values]
[1, 0, 4, 0]
答案 2 :(得分:2)
df['C'] = df.apply(lambda row: min([abs(x - y) for x in row['A'] for y in row['B']], default=0), axis=1)
答案 3 :(得分:1)
我只想再次介绍unnesting
df['Diff']=unnesting(df[['B']],['B']).join(unnesting(df[['A']],['A'])).eval('C=B-A').C.abs().min(level=0)
df.Diff=df.Diff.fillna(0).astype(int)
df
Out[60]:
A B Diff
0 [1, 5, 10] [15, 2] 1
1 [] [] 0
2 [2] [6] 4
3 [1, 2] [] 0
仅供参考
def unnesting(df, explode):
idx=df.index.repeat(df[explode[0]].str.len())
df1=pd.concat([pd.DataFrame({x:np.concatenate(df[x].values)} )for x in explode],axis=1)
df1.index=idx
return df1.join(df.drop(explode,1),how='left')
答案 4 :(得分:0)
我认为这可行
def diff(a,b):
if len(a) > 0 and len(b) > 0:
return min([abs(i-j) for i in a for j in b])
return 0
df['C'] = df.apply(lambda x: diff(x.A, x.B), axis=1)
df
A B C
0 [1, 5, 10] [15, 2] 1
1 [] [] 0
2 [2] [6] 4
3 [1, 2] [] 0