Python-在多个数据框中交换值

时间:2018-10-24 16:19:56

标签: python pandas dataframe

我有一个这样的DataFrame

id  val1   val2
0    A      B
1    B      B
2    A      A
3    A      A

我想交换值,例如:

id  val1   val2
0    B      A
1    A      A
2    B      B
3    B      B

我需要考虑到df可能还有其他我想保持不变的列。

5 个答案:

答案 0 :(得分:4)

尝试stack ing,map ping,然后unstack ing:

df[['val1', 'val2']] = (
    df[['val1', 'val2']].stack().map({'B': 'A', 'A': 'B'}).unstack())

df
   id val1 val2
0   0    B    A
1   1    A    A
2   2    B    B
3   3    B    B

对于(更快)的解决方案,请使用嵌套列表理解。

mapping = {'B': 'A', 'A': 'B'}
df[['val1', 'val2']] = [
    [mapping.get(x, x) for x in row] for row in df[['val1', 'val2']].values]

df
   id val1 val2
0   0    B    A
1   1    A    A
2   2    B    B
3   3    B    B

答案 1 :(得分:4)

您可以将pd.DataFrame.applymap与字典配合使用:

d = {'B': 'A', 'A': 'B'}

df = df.applymap(d.get).fillna(df)

print(df)

  id val1 val2
0  0    B    A
1  1    A    A
2  2    B    B
3  3    B    B

为了提高性能(尤其是内存使用量),您可能希望使用categorical data

for col in df.columns[1:]:
    df[col] = df[col].astype('category')
    df[col] = df[col].cat.rename_categories(d)

答案 2 :(得分:4)

使用factorize并滚动相应的值

def swaparoo(col):
  i, r = col.factorize()
  return pd.Series(r[(i + 1) % len(r)], col.index)

df[['id']].join(df[['val1', 'val2']].apply(swaparoo))

   id val1 val2
0   0    B    A
1   1    A    A
2   2    B    B
3   3    B    B

使用相同功能的替代体操。它将整个数据帧合并到分解中。

df.set_index('id').stack().pipe(swaparoo).unstack().reset_index()

示例

df = pd.DataFrame(dict(id=range(4), val1=[*'ABAA'], val2=[*'BBAA']))

print(
    df,
    df.set_index('id').stack().pipe(swaparoo).unstack().reset_index(),
    sep='\n\n'
)

   id val1 val2
0   0    A    B
1   1    B    B
2   2    A    A
3   3    A    A

   id val1 val2
0   0    B    A
1   1    A    A
2   2    B    B
3   3    B    B

df = pd.DataFrame(dict(id=range(4), val1=[*'AAAA'], val2=[*'BBBB']))

print(
    df,
    df.set_index('id').stack().pipe(swaparoo).unstack().reset_index(),
    sep='\n\n'
)

   id val1 val2
0   0    A    B
1   1    A    B
2   2    A    B
3   3    A    B

   id val1 val2
0   0    B    A
1   1    B    A
2   2    B    A
3   3    B    A

df = pd.DataFrame(dict(id=range(4), val1=[*'AAAA'], val2=[*'BBBB'], val3=[*'CCCC']))

print(
    df,
    df.set_index('id').stack().pipe(swaparoo).unstack().reset_index(),
    sep='\n\n'
)

   id val1 val2 val3
0   0    A    B    C
1   1    A    B    C
2   2    A    B    C
3   3    A    B    C

   id val1 val2 val3
0   0    B    C    A
1   1    B    C    A
2   2    B    C    A
3   3    B    C    A

df = pd.DataFrame(dict(id=range(4), val1=[*'ABCD'], val2=[*'BCDA'], val3=[*'CDAB']))

print(
    df,
    df.set_index('id').stack().pipe(swaparoo).unstack().reset_index(),
    sep='\n\n'
)

   id val1 val2 val3
0   0    A    B    C
1   1    B    C    D
2   2    C    D    A
3   3    D    A    B

   id val1 val2 val3
0   0    B    C    D
1   1    C    D    A
2   2    D    A    B
3   3    A    B    C

答案 3 :(得分:4)

您可以使用numpy.where有效地交换两个值。但是,如果多于两个值,则此方法停止工作。

a = df[['val1', 'val2']].values
df[['val1', 'val2']] = np.where(a=='A', 'B', 'A')

   id val1 val2
0   0    B    A
1   1    A    A
2   2    B    B
3   3    B    B

要对此进行调整,请保持其他值不变,可以使用np.select

c1 = a=='A'
c2 = a=='B'
np.select([c1, c2], ['B', 'A'], a)

答案 4 :(得分:4)

使用replace:为什么在这里需要C,请检查this

df[['val1','val2']].replace({'A':'C','B':'A','C':'B'})
Out[263]: 
  val1 val2
0    B    A
1    A    A
2    B    B
3    B    B