我正在使用 apply()
从现有 DataFrame 的值构造一系列元组。我需要在元组中构建值的特定顺序,并将除一列之外的所有列中的 NaN
替换为 '{}'
。
以下函数可以产生所需的结果,但执行速度相当慢:
def build_insert_tuples_series(row):
# Here I attempt to handle ordering the final tuple
# I must also replace NaN with "{}" for all but v2 column.
vals = [row['v2']]
row_sans_v2 = row.drop(labels=['v2'])
row_sans_v2.fillna("{}", inplace=True)
res = [val for val in row_sans_token]
vals += res
return tuple(vals)
def generate_insert_values_series(df):
df['insert_vals'] = df.apply(lambda x: build_insert_tuples_series(x), axis=1)
return df['insert_vals']
原始数据框:
id v1 v2
0 1.0 foo quux
1 2.0 bar foo
2 NaN NaN baz
调用 generate_insert_values_series(df)
时产生的 DataFrame:
最终元组的排序逻辑是(v2, ..all_other_columns..)
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, {}, {})
对函数进行计时以生成结果 DataFrame:
%%timeit
generate_insert_values_series(df)
100 loops, best of 3: 2.69 ms per loop
我觉得可能有一种方法可以更有效地构建系列,但不确定如何使用矢量化或其他方法优化操作。
最佳答案
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)))
关于python - 高效地从 pandas DataFrame 创建一系列元组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52858015/