【问题标题】:Substitute values from one pandas data frame to another based on condition根据条件将一个熊猫数据帧中的值替换为另一个数据帧
【发布时间】:2016-05-21 13:30:11
【问题描述】:

我有两个包含多列的数据框。

df_1 = pd.DataFrame({'A': ['x', '-', 'z'], 'B': [1, 6, 9], 'C': [2, 1, '-']})
> df_1

   A  B  C
0  x  1  2
1  -  6  1
2  z  9  -

df_2 = pd.DataFrame({'A': ['w', 'y', 'y'], 'B': [5, 6, 9], 'C': [2, 1, 8]})
> df_2

   A  B  C
0  w  5  2
1  y  6  1
2  y  9  8

如何根据条件(布尔掩码)将一个数据帧中的值替换为另一个数据帧中的值? 在这里,缺失值标注为'-',我想使用df_2 中的值来获取结果:

> df
   A  B  C
0  x  1  2
1  y  6  1
2  z  9  8   

【问题讨论】:

  • 请问您期望的过程和结果??
  • 谢谢,没注意我没有添加

标签: python pandas dataframe


【解决方案1】:

IIUC 您可以创建boolean mask,通过astype 将值转换为string,然后与- 进行比较。最后用- 填充值来自另一个DataFrame 通过maskwhere 与反转mask 通过~

mask = df_1.astype(str) == '-'
print (mask)
       A      B      C
0  False  False  False
1   True  False  False
2  False  False   True

print (df_1.mask(mask, df_2))
   A  B  C
0  x  1  2
1  y  6  1
2  z  9  8

print (df_1.where(~mask, df_2))
   A  B  C
0  x  1  2
1  y  6  1
2  z  9  8

通过评论编辑:

su79eu7k 提供一个可能的解决方案,谢谢:

masks = [('A', r'[a-zA-Z]'), ('B', r'\d'), ('C', r'\d')]; 
print pd.concat([~(df_1[col].astype(str).str.contains(regex)) for col, regex in masks], axis=1)

另一种解决方案创建mask - 首先是fillna 可能的NaN 值,然后是replacedictNaN 的缺失值,最后找到isnull 值。

import pandas as pd
import numpy as np

df_1 = pd.DataFrame({'A': ['-x', '-', np.nan],'B': [1, 6, 'Unknown'],'C': [2, 1, 'Missing']})
print (df_1)

df_2 = pd.DataFrame({'A': ['w', 'y', 'y'], 'B': [5, 6, 9], 'C': [2, 1, 8]})
print (df_2)

mask_li = ['-','Unknown','Missing']  
d = {x:np.nan for x in mask_li}  

mask = df_1.fillna(1).replace(d).isnull()
print (mask)
       A      B      C
0  False  False  False
1   True  False  False
2  False   True   True

print (df_1.mask(mask, df_2))    
     A  B  C
0   -x  1  2
1    y  6  1
2  NaN  9  8

您可以使用str.contains,但其他数据不能包含列表mask_li中的值:

mask_li = ['-','Unknown','Missing']    

mask= df_1.copy()
for col in df_1.columns:
    mask[col] = mask[col].astype(str).str.contains('|'.join(mask_li))

print (mask)
       A      B      C
0  False  False  False
1   True  False  False
2  False   True   True

print (df_1.mask(mask, df_2))    
   A  B  C
0  x  1  2
1  y  6  1
2  z  9  8

但是,如果另一个数据包含来自mask_li 的值,例如-:

例如:

import pandas as pd
import numpy as np

df_1 = pd.DataFrame({'A': ['-x', '-', '-z'], 'B': [1, 6, 'Unknown'], 'C': [2, 1, 'Missing']})
print (df_1)

df_2 = pd.DataFrame({'A': ['w', 'y', 'y'], 'B': [5, 6, 9], 'C': [2, 1, 8]})
print (df_2)

mask_li = ['-','Unknown','Missing']    

mask= df_1.copy()
for col in df_1.columns:
    mask[col] = mask[col].astype(str).str.contains('|'.join(mask_li))

print (mask)
      A      B      C
0  True  False  False
1  True  False  False
2  True   True   True

print (df_1.mask(mask, df_2))    
   A  B  C
0  w  1  2
1  y  6  1
2  y  9  8

一种可能的解决方案:

import pandas as pd
import numpy as np

df_1 = pd.DataFrame({'A': ['-x', '-', '-z'], 'B': [1, 6, 'Unknown'], 'C': [2, 1, 'Missing']})
print (df_1)

df_2 = pd.DataFrame({'A': ['w', 'y', 'y'], 'B': [5, 6, 9], 'C': [2, 1, 8]})
print (df_2)

mask_li = ['Unknown','Missing']    

mask= df_1.copy()
for col in df_1.columns:
    column = mask[col].astype(str)
    mask[col] = (column.str.contains('|'.join(mask_li))) | (column == '-')

print (mask)
       A      B      C
0  False  False  False
1   True  False  False
2  False   True   True

print (df_1.mask(mask, df_2))    
    A  B  C
0  -x  1  2
1   y  6  1
2  -z  9  8

【讨论】:

  • 非常感谢!如果我有几种类型的缺失值,如'-''Missed''Unknown' 等,您能否建议我该怎么做..
  • 一种方法是mask = (df_1.astype(str) == '-') | ( df_1.astype(str) == 'Missed') ,但是如果遗漏值列表太长就不合适了。
  • @KatrinaMalakhova 那么您可能需要正则表达式来制作更强大的掩码,例如 masks = [('A', r'[a-zA-Z]'), ('B', r'\d'), ('C', r'\d')]; print pd.concat([~(df_1[col].astype(str).str.contains(regex)) for col, regex in masks], axis=1) 过滤列 A 中的非字母和列 BC 中的非数字。跨度>
猜你喜欢
  • 2020-04-28
  • 2022-01-24
  • 1970-01-01
  • 2018-08-18
  • 2021-03-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多