python - 使用 lambda 基于具有非空值的另一列在数据框中创建一列
问题描述
我有带有电影标题的数据框和带有流派的列。例如标题为“One”的电影是“Action”和“Vestern”,因为在适当的列中有“1”。
Movie Action Fantasy Vestern
0 One 1 0 1
1 Two 0 0 1
2 Three 1 1 0
我的目标是创建列genres
,其中将包含特定电影所具有的每种类型的名称。为此,我尝试使用lambda
and list comprehension
,因为认为这会有所帮助。但是在运行如下代码行之后:
df['genres'] = df.apply(lambda x: [x+"|"+x for x in df.columns if x!=0])
我NaN
在每一行中只有值:
Movie Action Fantasy Vestern genres
0 One 1 0 1 NaN
1 Two 0 0 1 NaN
2 Three 1 1 0 NaN
也尝试使用groupby
,但没有成功。
预期输出为:
Movie Action Fantasy Vestern genres
0 One 1 0 1 Action|Vestern
1 Two 0 0 1 Vestern
2 Three 1 1 0 Action|Fantasy
重现代码:
import pandas as pd
import numpy as np
df = pd.DataFrame({"Movie":['One','Two','Three'],
"Action":[1,0,1],
"Fantasy":[0,0,1],
"Vestern":[1,1,0]})
print(df)
谢谢你的帮助
解决方案
为了提高性能,可以使用dot
所有没有第一个的列和所有没有最后一个的列,separator
最后一个删除最后一个:|
rstrip
df['new'] = df.iloc[:, 1:].dot(df.columns[1:] + '|').str.rstrip('|')
print (df)
Movie Action Fantasy Vestern new
0 One 1 0 1 Action|Vestern
1 Two 0 0 1 Vestern
2 Three 1 1 0 Action|Fantasy
或者使用列表推导来连接所有没有空字符串的值:
arr = df.iloc[:, 1:].values * df.columns[1:].values
df['new'] = ['|'.join(y for y in x if y) for x in arr]
print (df)
Movie Action Fantasy Vestern new
0 One 1 0 1 Action|Vestern
1 Two 0 0 1 Vestern
2 Three 1 1 0 Action|Fantasy
性能:
In [54]: %timeit (jez1(df.copy()))
25.2 ms ± 2.31 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
In [55]: %timeit (jez2(df.copy()))
61.4 ms ± 769 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
In [56]: %timeit (csm(df.copy()))
1.46 s ± 35.7 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
df = pd.DataFrame({"Movie":['One','Two','Three'],
"Action":[1,0,1],
"Fantasy":[0,0,1],
"Vestern":[1,1,0]})
#print(df)
#30k rows
df = pd.concat([df] * 10000, ignore_index=True)
def csm(df):
cols = df.columns.tolist()[1:]
df['genres'] = df.apply(lambda x: "|".join(str(z) for z in [i for i in cols if x[i] !=0]) ,axis=1)
return df
def jez1(df):
df['new'] = df.iloc[:, 1:].dot(df.columns[1:] + '|').str.rstrip('|')
return df
def jez2(df):
arr = df.iloc[:, 1:].values * df.columns[1:].values
df['new'] = ['|'.join(y for y in x if y) for x in arr]
return df
推荐阅读
- html - 如何使按钮更明显?
- rust - 有没有办法告诉 Rust 的 drop checker 我们有效地拥有一个 `T` 而它不在泛型参数中?
- apache-spark - 优化 Spark 资源以避免内存和空间使用
- python-3.x - Ms Azure 认知快速入门 Speech to Text(添加短语以确保准确性)
- mercurial - 如何在 rhodecode 扩展中获取 mercurial 变更集的文件
- javascript - UnhandledPromiseRejectionWarning: DiscordAPIError: Unknown Role in my code
- ios - 如何为独立 watchOS 应用添加 iOS 图标
- c# - 如何在实体框架中创建新记录而不在其参数中指定主键?
- c++ - 为什么在条件评估中最后进行后缀增量?
- python - 如何添加嵌套图层和小部件?