use*_*546 2 python functional-programming pipeline dataframe pandas
我想知道哪种函数式编程的最佳实践是编写一系列函数来处理熊猫数据框-或任何其他可变输入类型-作为函数的输入。
这里有两个想法,但是希望有更好的东西:)
想法#1-不进行功能编程而是节省内存
def foo(df, param):
df['col'] = df['col'] + param
def pipeline(df):
foo(df, 1)
foo(df, 2)
foo(df, 3)
Run Code Online (Sandbox Code Playgroud)
想法#2-更多的功能编程,但是通过执行.copy()浪费了内存
def foo(df, param):
df = df.copy()
df['col'] = df['col'] + param
return df
def pipeline(df):
df1 = foo(df, 1)
df2 = foo(df1, 2)
df3 = foo(df2, 3)
Run Code Online (Sandbox Code Playgroud)
您可以链接在数据帧上运行的函数调用。还可以看看DataFrame.pipe
熊猫。像这样,添加了两个非foo操作:
df = (df.pipe(foo,1)
.pipe(foo,2)
.pipe(foo,3)
.drop(columns=['drop','these'])
.assign(NEW_COL=lambda x: x['OLD_COL'] / 10))
Run Code Online (Sandbox Code Playgroud)
df
将是foo
您使用时传递给它的第一个参数pipe
。
如果您的数据框是一维的(即它是一个项目列表),那么您可以一次完成所有操作,而不是应用多个“管道”。例如我们有一个数据框
>>> table
Name Year of Birth City
0 Mike 1970 New York
1 Chris 1981 Miami
2 Janine 1975 Seattle
Run Code Online (Sandbox Code Playgroud)
我们想要计算年龄并检查一个人是否住在迈阿密。您可以应用 2 个管道,但也可以使用单个 lambda 来完成:
>>> f = lambda s: pd.Series([2019 - s['Year of Birth'], s['City'] == 'Miami'])
Run Code Online (Sandbox Code Playgroud)
然后应用它
>>> table[['Age', 'Lives in Miami']] = table.apply(f, axis=1)
>>> table
Name Year of Birth City Age Lives in Miami
0 Mike 1970 New York 49 False
1 Chris 1981 Miami 38 True
2 Janine 1975 Seattle 44 False
Run Code Online (Sandbox Code Playgroud)
所有工作均在 中完成f
。
另一个例子:假设您想检查谁的年龄超过 45 岁。这包含两个串行操作(前面的示例是 2 个并行操作):
您可以使用 2 个管道,但同样可以通过应用单个 lambda 来完成这一切:
>>> table
Name Year of Birth City
0 Mike 1970 New York
1 Chris 1981 Miami
2 Janine 1975 Seattle
>>> g = lambda s: pd.Series([2019 - s['Year of Birth'] > 45])
>>> table['Older than 45'] = table.apply(g, axis=1)
>>> table
Name Year of Birth City Older than 45
0 Mike 1970 New York True
1 Chris 1981 Miami False
2 Janine 1975 Seattle False
Run Code Online (Sandbox Code Playgroud)
如果您喜欢不变性,那么就这样做
>>> table
Name Year of Birth City
0 Mike 1970 New York
1 Chris 1981 Miami
2 Janine 1975 Seattle
>>> pd.concat([table, table.apply(f, axis=1)], axis=1)
Name Year of Birth City 0 1
0 Mike 1970 New York 49 False
1 Chris 1981 Miami 38 True
2 Janine 1975 Seattle 44 False
Run Code Online (Sandbox Code Playgroud)
如果你不喜欢 lambda 则定义
def f(s):
return pd.Series([2019 - s['Year of Birth'],
s['City'] == 'Miami'])
Run Code Online (Sandbox Code Playgroud)
仅当您想要应用仅需要在单个行上工作的映射时,这一切才有效。另外,我没有对速度做出任何声明,管道可能会更快,但是这是非常可读的。
(最后你意识到你最好使用 Haskell。)