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
解释:
- 查找
ColumnA
是 Nan
但 ColumnB
不是 的索引
- 对于这些索引中的每一个,将
ColumnB
的前一行中的 Nan
值替换为当前行中的值
- 使当前行的值为
ColumnB
Nan
- 调用
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
作为逻辑语句的主语。有一个更简单的方法:
- 如果
ColumnB
为空,则使用它下面的行。如果不是,则保留其原始值。
- 如果
ColumnA
为 'not_translated',则在 ColumnB
中保留空值。
- 删除
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 . .
非常感谢您的帮助!很高兴能够访问这样一个伟大的社区 :) 已编辑
我这两天都在拼命的解决这个问题,真的很希望得到大家的帮助。
我有一个 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
解释:
- 查找
ColumnA
是Nan
但ColumnB
不是 的索引
- 对于这些索引中的每一个,将
ColumnB
的前一行中的Nan
值替换为当前行中的值 - 使当前行的值为
ColumnB
Nan
- 调用
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
作为逻辑语句的主语。有一个更简单的方法:
- 如果
ColumnB
为空,则使用它下面的行。如果不是,则保留其原始值。 - 如果
ColumnA
为 'not_translated',则在ColumnB
中保留空值。 - 删除
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 . .