Python 根据另一列中的 Nan 或布尔值移动一列中的值

Python Shift values in one column based on Nan or boolean in other column

非常感谢您的帮助!很高兴能够访问这样一个伟大的社区 :) 已编辑

我这两天都在拼命的解决这个问题,真的很希望得到大家的帮助。

我有一个 table 看起来像这样:

A 列 B 列 C 列
这个 1
达斯 2
3
4
一个 5
ein 6
not_translated 7
文本 文字 8
, 9
10
, 11
12
所以 13
所以 14
. 15
. 16

我现在希望当 A 列中没有任何内容时,ColumnB 中的每个翻译都向上移动一行(以便“This”和“Das”在同一行),但在以下情况下保持在同一行ColumnA 中有文本(如“文本”和“文本”)。所以我想要达到的结果是:

A 列 B 列 C 列
这个 达斯 1
3
一个 ein 5
not_translated 7
文本 文字 8
, , 9
12
所以 所以 13
. . 15

到目前为止我尝试过使用布尔值,但没有成功:

df1['bool'] = (df1['ColumnA'].isnull())
if df1['bool']:
    df1['ColumnB'].shift(periods=-1)
else:
    df1['ColumnB']

以及使用 np.where:

df1["ColumnB"] = np.where((df1["ColumnA"].isnull()), df1["ColumnB"].shift(periods=-1), df1["ColumnB"])

最好将 ColumnB 中的翻译向上移动到 ColumnA 的下一行文本(这是我最初的尝试,但不幸的是它没有成功)。 非常感谢您迄今为止的帮助和努力!

这是您可以尝试的一种方法:

代码:

df = df.dropna(axis=0, subset=['ColumnA', 'ColumnB'], how='all').reset_index(drop=True)

idxs=df[df['ColumnA'].isna() & df['ColumnB'].notna()].index.tolist()

for i in idxs:
    df['ColumnB'].iloc[i-1] = df['ColumnB'].iloc[i]
    df['ColumnB'].iloc[i] = np.NaN

df = df.dropna(axis=0, subset=['ColumnA', 'ColumnB'], how='all').reset_index(drop=True)
print(df)

输入:

           ColumnA ColumnB  ColumnC
0             This     NaN        1
1              NaN     Das        2
2               is     NaN        3
3              NaN     ist        4
4                a     NaN        5
5              NaN     ein        6
6   not_translated     NaN        7
7             text    Text        8
8                ,     NaN        9
9              NaN     NaN       10
10             NaN       ,       11
11             and     und       12
12              so     NaN       13
13             NaN      so       14
14               .     NaN       15
15             NaN       .       16

输出:

          ColumnA ColumnB  ColumnC
0            This     Das        1
1              is     ist        3
2               a     ein        5
3  not_translated     NaN        7
4            text    Text        8
5               ,       ,        9
6             and     und       12
7              so      so       13
8               .       .       15

解释:

  1. 查找 ColumnANanColumnB 不是
  2. 的索引
  3. 对于这些索引中的每一个,将 ColumnB 的前一行中的 Nan 值替换为当前行中的值
  4. 使当前行的值为ColumnBNan
  5. 调用 dropna 删除不需要的行

根据要求的变化进行编辑:

不使用循环的方法:

df = df.dropna(subset=['ColumnA', 'ColumnB'], how='all').copy()
m = df['ColumnB'].shift(-1).notna() & df['ColumnA'].shift(-1).isna() & df['ColumnB'].isna()
df.loc[m, 'ColumnB'] = df['ColumnB'].shift(-1)
df = df.dropna(subset=['ColumnA'])

数据输入:

           ColumnA ColumnB  ColumnC
0             This     NaN        1
1              NaN     Das        2
2               is     NaN        3
3              NaN     ist        4
4                a     NaN        5
5              NaN     ein        6
6   not_translated     NaN        7
7             text    Text        8
8                ,     NaN        9
9              NaN     NaN       10
10             NaN       ,       11
11             and     und       12
12              so     NaN       13
13             NaN      so       14
14               .     NaN       15
15             NaN       .       16

结果:

           ColumnA ColumnB  ColumnC
0             This     Das        1
2               is     ist        3
4                a     ein        5
6   not_translated     NaN        7
7             text    Text        8
8                ,       ,        9
11             and     und       12
12              so      so       13
14               .       .       15

您正在使用 ColumnA 作为逻辑语句的主语。有一个更简单的方法:

  1. 如果 ColumnB 为空,则使用它下面的行。如果不是,则保留其原始值。
  2. 如果 ColumnA 为 'not_translated',则在 ColumnB 中保留空值。
  3. 删除 ColumnA 为空的行。

在代码中:

# If B is null, take next value. Otherwise, keep value.
df['ColumnB_new'] = np.where(df['ColumnB'].notna(), df['ColumnB'], df['ColumnB'].shift(-1))

# If A is 'not_tranlsated', leave null
df['ColumnB_new'] = np.where(df['ColumnA'].eq('not_translated'), np.nan, df['ColumnB_new'])

# Result
df = df.loc[df['ColumnA'].notna(), ['ColumnA','ColumnB_new']]
print(df)

          ColumnA ColumnB_new
0            This         Das
2              is         ist
4               a         ein
6  not_translated         NaN
7            text        text
8               .           .