3 回答
TA贡献1752条经验 获得超4个赞
zip, get, mask, fillna, 和sorted
一件物有所值
df.assign(
insert_vals=
[*zip(*map(df.mask(df.isna(), {}).get, sorted(df, key=lambda x: x != 'v2')))])
id v1 v2 insert_vals
0 1.0 foo quux (quux, 1.0, foo)
1 2.0 bar foo (foo, 2.0, bar)
2 NaN NaN baz (baz, {}, {})
少一行字
get = df.mask(df.isna(), {}).get
key = lambda x: x != 'v2'
cols = sorted(df, key=key)
df.assign(insert_vals=[*zip(*map(get, cols))])
id v1 v2 insert_vals
0 1.0 foo quux (quux, 1.0, foo)
1 2.0 bar foo (foo, 2.0, bar)
2 NaN NaN baz (baz, {}, {})
这应该适用于旧版 python
get = df.mask(df.isna(), {}).get
key = lambda x: x != 'v2'
cols = sorted(df, key=key)
df.assign(insert_vals=zip(*map(get, cols)))
TA贡献1865条经验 获得超7个赞
你不应该要做到这一点,因为你的新系列将失去所有的矢量化功能。
但是,如果必须,您可以apply通过使用pd.DataFrame.itertuples列表推导式或map. 唯一的复杂之处是重新排序列,您可以通过转换为list:
df = pd.concat([df]*10000, ignore_index=True)
col_lst = df.columns.tolist()
cols = [col_lst.pop(col_lst.index('v2'))] + col_lst
%timeit list(df[cols].itertuples(index=False)) # 31.3 ms per loop
%timeit [tuple(x) for x in df[cols].values] # 74 ms per loop
%timeit list(map(tuple, df[cols].values)) # 73 ms per loop
上面的基准测试是在 Python 3.6.0 上进行的,但您可能会发现这些比apply在 2.7 上更有效。请注意,list最终版本不需要转换,因为在 v2.7 中map返回 a list。
如果绝对必要,您可以fillna通过一系列:
s = pd.Series([{} for _ in range(len(df.index))], index=df.index)
for col in df[cols]:
df[cols].fillna(s)
TA贡献1868条经验 获得超4个赞
首先,您可以使用numpy替换null值dicts
import pandas as pd
import numpy as np
temp = pd.DataFrame({'id':[1,2, None], 'v1':['foo', 'bar', None], 'v2':['quux', 'foo', 'bar']})
def replace_na(col):
return np.where(temp[col].isnull(), '{}', temp[col])
def generate_tuple(df):
df['id'], df['v1'] = replace_na('id'), replace_na('v1')
return df.apply(lambda x: tuple([x['v2'], x['id'], x['v1']]), axis=1)
你的收获是
%%timeit
temp['insert_tuple'] = generate_tuple(temp)
>>>> 1000 loops, best of 3 : 1ms per loop
如果您将其更改generate_tuple return为类似
def generate_tuple(df):
df['id'], df['v1'] = replace_na('id'), replace_na('v1')
return list(zip(df['v2'], df['id'], df['v1']))
你的收益变成:
%%timeit
temp['insert_tuple'] = generate_tuple(temp)
1000 loops, best of 3 : 674 µs per loop
添加回答
举报