使用 Pandas 替换行中 removing/replacing 字符后的数据帧值
Replacing dataframe values after removing/replacing character in rows using Pandas
我有一个数据框 df_in
像这样:
import pandas as pd
import numpy as np
dic_in = {'A':['aa','bb','cc','dd','ee','ff','gg','uu','xx','yy','zz'],
'B':['200','200','AA200','AA040',np.nan,'500',np.nan,'0700','900','UKK','200'],
'C':['UNN','400',np.nan,'AA080','AA800','B',np.nan,'400',np.nan,'500','UKK']}
我的目标是通过以下方式调查列 B
和 C
:
- 如果其中一项包含以下字符
'AA'
,则必须删除字符串的数字部分,只留下数字部分。 (AA123 ---> 123
)。如果在第一个非空元素之前存在零,则必须将其删除 (AA001234 ---> 1234
)。
- 如果数量不是数字则必须设置为
0.0
(NaN ---> 0.0
、UNN ----> 0.0
、UKK ---> 0.0
等)。
- 如果某项之前有前导零,则必须删除它们(
070--->700
、00007000--->7000
)
- 如果某项已修改且非零,则必须乘以
100
。
最终结果应该是这样的:
# BEFORE # # AFTER #
A B C A B C
0 aa 200 UNN 0 aa 200 0.0
1 bb 200 400 1 bb 200 400
2 cc AA200 NaN 2 cc 20000 0.0
3 dd AA040 AA080 3 dd 4000 8000
4 ee NaN AA800 4 ee 0.0 80000
5 ff 500 B 5 ff 500 0.0
6 gg NaN NaN 6 gg 0.0 0.0
7 uu 0700 400 7 uu 700 400
8 xx 900 NaN 8 xx 900 0.0
9 yy UKK 500 9 yy 0.0 500
10 zz 200 UKK 10 zz 200 0.0
你知道实现这个目标的聪明有效的方法吗?
注意:所有数字实际上都是字符串,应该保持原样。
您可以使用 to_numeric
将非数字替换为 NaN
。
然后 extract
numbers from strings, remove 0
from left by lstrip
并添加 00
.
最后 combine_first
with fillna
并分配给列:
b = pd.to_numeric(df_in.B, errors='coerce')
c = pd.to_numeric(df_in.C, errors='coerce')
b1 = df_in.B.str.extract('(\d+)', expand=False).str.lstrip('0') + '00'
c1 = df_in.C.str.extract('(\d+)', expand=False).str.lstrip('0') + '00'
df_in.B = b.combine_first(b1).fillna(0)
df_in.C = c.combine_first(c1).fillna(0)
print (df_in)
A B C
0 aa 200 0
1 bb 200 400
2 cc 20000 0
3 dd 4000 8000
4 ee 0 80000
5 ff 500 0
6 gg 0 0
7 uu 700 400
8 xx 900 0
9 yy 0 500
10 zz 200 0
对最后 fillna
字符串 0.0
的一点修改解决方案将所有值转换为字符串(避免一些字符串和一些数值):
b = pd.to_numeric(df_in.B, errors='coerce')
c = pd.to_numeric(df_in.C, errors='coerce')
b1 = df_in.B.str.extract('(\d+)', expand=False).str.lstrip('0') + '00'
c1 = df_in.C.str.extract('(\d+)', expand=False).str.lstrip('0') + '00'
df_in.B = b.combine_first(b1)
df_in.C = c.combine_first(c1)
df_in = df_in.fillna('0.0').astype(str)
print (df_in)
A B C
0 aa 200.0 0.0
1 bb 200.0 400.0
2 cc 20000 0.0
3 dd 4000 8000
4 ee 0.0 80000
5 ff 500.0 0.0
6 gg 0.0 0.0
7 uu 700.0 400.0
8 xx 900.0 0.0
9 yy 0.0 500.0
10 zz 200.0 0.0
假设你的dataframe中的所有值都是字符串(包括NaN
s,否则你可以用fillna
将它们转换成合适的字符串),你可以使用下面的converter
函数与 applymap
在要转换的两列上。
df = pd.DataFrame(dic_in, dtype=str).fillna('NAN')
converter = lambda x: str(int(x.replace('AA', ''))*100) if 'AA' in x else str(int(x)) if x.isdigit() else '0.0'
df[['B','C']] = df[['B','C']].applymap(converter)
df
的内容:
A B C
0 aa 200 0.0
1 bb 200 400
2 cc 20000 0.0
3 dd 4000 8000
4 ee 0.0 80000
5 ff 500 0.0
6 gg 0.0 0.0
7 uu 700 400
8 xx 900 0.0
9 yy 0.0 500
10 zz 200 0.0
我有一个数据框 df_in
像这样:
import pandas as pd
import numpy as np
dic_in = {'A':['aa','bb','cc','dd','ee','ff','gg','uu','xx','yy','zz'],
'B':['200','200','AA200','AA040',np.nan,'500',np.nan,'0700','900','UKK','200'],
'C':['UNN','400',np.nan,'AA080','AA800','B',np.nan,'400',np.nan,'500','UKK']}
我的目标是通过以下方式调查列 B
和 C
:
- 如果其中一项包含以下字符
'AA'
,则必须删除字符串的数字部分,只留下数字部分。 (AA123 ---> 123
)。如果在第一个非空元素之前存在零,则必须将其删除 (AA001234 ---> 1234
)。 - 如果数量不是数字则必须设置为
0.0
(NaN ---> 0.0
、UNN ----> 0.0
、UKK ---> 0.0
等)。 - 如果某项之前有前导零,则必须删除它们(
070--->700
、00007000--->7000
) - 如果某项已修改且非零,则必须乘以
100
。
最终结果应该是这样的:
# BEFORE # # AFTER #
A B C A B C
0 aa 200 UNN 0 aa 200 0.0
1 bb 200 400 1 bb 200 400
2 cc AA200 NaN 2 cc 20000 0.0
3 dd AA040 AA080 3 dd 4000 8000
4 ee NaN AA800 4 ee 0.0 80000
5 ff 500 B 5 ff 500 0.0
6 gg NaN NaN 6 gg 0.0 0.0
7 uu 0700 400 7 uu 700 400
8 xx 900 NaN 8 xx 900 0.0
9 yy UKK 500 9 yy 0.0 500
10 zz 200 UKK 10 zz 200 0.0
你知道实现这个目标的聪明有效的方法吗?
注意:所有数字实际上都是字符串,应该保持原样。
您可以使用 to_numeric
将非数字替换为 NaN
。
然后 extract
numbers from strings, remove 0
from left by lstrip
并添加 00
.
最后 combine_first
with fillna
并分配给列:
b = pd.to_numeric(df_in.B, errors='coerce')
c = pd.to_numeric(df_in.C, errors='coerce')
b1 = df_in.B.str.extract('(\d+)', expand=False).str.lstrip('0') + '00'
c1 = df_in.C.str.extract('(\d+)', expand=False).str.lstrip('0') + '00'
df_in.B = b.combine_first(b1).fillna(0)
df_in.C = c.combine_first(c1).fillna(0)
print (df_in)
A B C
0 aa 200 0
1 bb 200 400
2 cc 20000 0
3 dd 4000 8000
4 ee 0 80000
5 ff 500 0
6 gg 0 0
7 uu 700 400
8 xx 900 0
9 yy 0 500
10 zz 200 0
对最后 fillna
字符串 0.0
的一点修改解决方案将所有值转换为字符串(避免一些字符串和一些数值):
b = pd.to_numeric(df_in.B, errors='coerce')
c = pd.to_numeric(df_in.C, errors='coerce')
b1 = df_in.B.str.extract('(\d+)', expand=False).str.lstrip('0') + '00'
c1 = df_in.C.str.extract('(\d+)', expand=False).str.lstrip('0') + '00'
df_in.B = b.combine_first(b1)
df_in.C = c.combine_first(c1)
df_in = df_in.fillna('0.0').astype(str)
print (df_in)
A B C
0 aa 200.0 0.0
1 bb 200.0 400.0
2 cc 20000 0.0
3 dd 4000 8000
4 ee 0.0 80000
5 ff 500.0 0.0
6 gg 0.0 0.0
7 uu 700.0 400.0
8 xx 900.0 0.0
9 yy 0.0 500.0
10 zz 200.0 0.0
假设你的dataframe中的所有值都是字符串(包括NaN
s,否则你可以用fillna
将它们转换成合适的字符串),你可以使用下面的converter
函数与 applymap
在要转换的两列上。
df = pd.DataFrame(dic_in, dtype=str).fillna('NAN')
converter = lambda x: str(int(x.replace('AA', ''))*100) if 'AA' in x else str(int(x)) if x.isdigit() else '0.0'
df[['B','C']] = df[['B','C']].applymap(converter)
df
的内容:
A B C
0 aa 200 0.0
1 bb 200 400
2 cc 20000 0.0
3 dd 4000 8000
4 ee 0.0 80000
5 ff 500 0.0
6 gg 0.0 0.0
7 uu 700 400
8 xx 900 0.0
9 yy 0.0 500
10 zz 200 0.0