有效地将每行的前导零转换为numpy.熊猫里的南



我有一个像这样的pandas数据框架:

thing1  thing2   num_col1    num_col2   num_col3    num_col4
aaa     abc      0.0         99.76     101.1        111.2
bbb     cde      11.3        109.76    201.1        121.2
ccc     def      91.3        0.0       301.1        131.2
.....
.....
aaa     efg      0.0         0.0       401.1        141.2
bbb     fgh      41.3        299.76    0.0          151.2
ccc     ghi      201.3       199.76    601.1        161.2

,我想把它转换成这样:

thing1  thing2   num_col1    num_col2   num_col3    num_col4
aaa     abc      nan         99.76     101.1        111.2
bbb     cde      11.3        109.76    201.1        121.2
ccc     def      91.3        0.0       301.1        131.2
.....
.....
aaa     efg      nan         nan       401.1        141.2
bbb     fgh      41.3        299.76    0.0          151.2
ccc     ghi      201.3       199.76    601.1        161.2

说明:如果num_col1num_col2num_col3num_col4列的值以0开头,则需要将这些0转换为numpy.nan,并且不能触及列中间的任何0。我如何尽可能高效地做到这一点(通过使用任何内置函数,而不是使用python的循环等,)?

IIUC,您可以为num_col列创建一个等于零的掩码数据帧,并遍历num_col列,检查num_col1和迭代num_col列之间的值是否都为True。

cols = df.filter(like='num_col').columns
m = df[cols].eq(0)
for idx, col in enumerate(cols[1:]):
m[col] = m[cols[:idx+2]].all(axis=1)
df[cols] = df[cols].mask(m, np.nan)
print(df)
thing1 thing2  num_col1  num_col2  num_col3  num_col4
0    aaa    abc       NaN     99.76     101.1     111.2
1    bbb    cde      11.3    109.76     201.1     121.2
2    ccc    def      91.3      0.00     301.1     131.2
3    aaa    efg       NaN       NaN     401.1     141.2
4    bbb    fgh      41.3    299.76       0.0     151.2
5    ccc    ghi     201.3    199.76     601.1     161.2

如果你也允许0从右开始,你可以试试

for idx, col in enumerate(cols[1:-1]):
m[col] = (m[cols[:idx+2]].all(axis=1)) | (m[cols[idx+1:]].all(axis=1))

要得到起始的0,通常需要对否定条件加和。像这样:

mask = (df.filter(like='num_') # extract numeric data, modify if needed
.ne(0)               # where the numbers are not 0
.cumsum(axis=1)      # these shows the blocks of `0`  
.eq(0)               # rows starting with zero 
)

那么你将得到掩码为:

num_col1  num_col2  num_col3  num_col4
0      True     False     False     False
1     False     False     False     False
2     False     False     False     False
3     False     False     False     False
4     False     False     False     False
5      True      True     False     False
6     False     False     False     False
7     False     False     False     False

最后,您可以使用mask来屏蔽您的数据:

df[mask.columns] = df[mask.columns].mask(mask)

你得到(注意5,num_col4行的0):

thing1 thing2  num_col1  num_col2  num_col3  num_col4
0    aaa    abc       NaN     99.76     101.1     111.2
1    bbb    cde      11.3    109.76     201.1     121.2
2    ccc    def      91.3      0.00     301.1     131.2
3  .....   None       NaN       NaN       NaN       NaN
4  .....   None       NaN       NaN       NaN       NaN
5    aaa    efg       NaN       NaN     401.1       0.0
6    bbb    fgh      41.3    299.76       0.0     151.2
7    ccc    ghi     201.3    199.76     601.1     161.2

最新更新