我有一个看起来像的df:
2017-04-03 2017-04-04 2017-04-05 2017-04-06
id
0 0.0 active 0.0 0.0
1 0.0 active 0.0 active
2 0.0 0.0 0.0 0.0
我想计算每行的零并将它们放入一个字符串来编码数据,但是只要没有连续的零,计数就需要重置。
对于上面的df,输出df看起来像:
2017-04-03 2017-04-04 2017-04-05 2017-04-06
id
0 inactive_1 active inactive_1 inactive_2
1 inactive_1 active inactive_1 active
2 inactive_1 inactive_2 inactive_3 inactive_4
这个函数让我非常接近,但不考虑重置cumsum,它只是对行中所有零实例求和。
def inactive(s):
np.where(s == 0, 'inactive_' + (s.eq(0).cumsum()).astype(str), s)
df.apply(inactive, 1)
一个小环形交叉口,但这可以通过在每一行上应用groupby
操作,然后使用np.where
有选择地将您的值应用于原始行来完成。
def f(x):
return x.groupby(x.ne(x.shift()).cumsum()).cumcount() + 1
i = df.apply(pd.to_numeric, errors='coerce')
j = 'inactive_' + i.apply(f, axis=1).astype(str)
df[:] = np.where(i.ne(0), df.values, j)
df
2017-04-03 2017-04-04 2017-04-05 2017-04-06
id
0 inactive_1 active inactive_1 inactive_2
1 inactive_1 active inactive_1 active
2 inactive_1 inactive_2 inactive_3 inactive_4
您可以使用:
#convert to numeric, NaNs for non numeric
df1 = df.apply(pd.to_numeric, errors='coerce')
#count consecutive values with reset
a = df1 == 0
b = a.cumsum(axis=1)
c = b-b.where(~a, axis=1).ffill(axis=1).fillna(0).astype(int)
print (c)
2017-04-03 2017-04-04 2017-04-05 2017-04-06
id
0 1 0 1 2
1 1 0 1 0
2 1 2 3 4
#replace by mask
df = df.mask(c != 0, 'inactive_' + c.astype(str))
print (df)
2017-04-03 2017-04-04 2017-04-05 2017-04-06
id
0 inactive_1 active inactive_1 inactive_2
1 inactive_1 active inactive_1 active
2 inactive_1 inactive_2 inactive_3 inactive_4
时序:
np.random.seed(425)
df = pd.DataFrame(np.random.choice([0, 'active'], size=(100000, 300)))
In [4]: %timeit (jez(df))
1 loop, best of 3: 1min 40s per loop
In [5]: %timeit col(df)
1 loop, best of 3: 5min 54s per loop
def jez(df):
df1 = df.apply(pd.to_numeric, errors='coerce')
#count consecutive values
a = df1 == 0
b = a.cumsum(axis=1)
c = b-b.where(~a, axis=1).ffill(axis=1).fillna(0).astype(int)
#replace by mask
return df.mask(c != 0, 'inactive_' + c.astype(str))
def f(x):
return x.groupby(x.ne(x.shift()).cumsum()).cumcount() + 1
def col(df):
i = df.apply(pd.to_numeric, errors='coerce')
j = 'inactive_' + i.apply(f, axis=1).astype(str)
df[:] = np.where(i.ne(0), df.values, j)
return(df)
警告:
性能实际上取决于数据。