我所拥有的:
我想做的事:
我已经有了下面的代码,它可以正常工作。然而,分析表明,这段代码是我代码中的一个重要瓶颈,因此如果可能的话,我想对其进行优化,我也有理由相信这应该是可能的:
df["NewColumn1"] = df.apply(lambda row: compute_new_column1_value(row), axis=1)
df["NewColumn2"] = df.apply(lambda row: compute_new_column2_value(row), axis=1)
# a few more lines of code like the above
我的解决方案基于对像这样的问题的回答(这是一个类似于我的问题,但特别是关于添加一个新列,而我的问题是关于添加许多新列)。我想这些df中的每一个。apply()
调用在内部是通过一个遍历所有行的循环实现的,我想应该可以通过一个只遍历所有循环一次的解决方案(而不是我想添加的每列一次)来优化它。
在其他答案中,我看到了对assign()函数的引用,它确实支持一次添加多个列。我试着用以下方式使用它:
# WARNING: this does NOT work
df = df.assign(
NewColumn1=lambda row: compute_new_column1_value(row),
NewColumn2=lambda row: compute_new_column2_value(row),
# more lines like the two above
)
这不起作用的原因是因为lambda实际上根本不接收数据帧的行作为参数,它们似乎只是一次获取整个数据帧。然后期望每个lambda一次返回完整的列/系列/数组值。所以,我这里的问题是,我必须通过那些lambda中的所有循环来实现手动循环,这显然会对性能造成更糟糕的影响。
我可以从概念上想到两种解决方案,但到目前为止还无法找到如何实际实施它们:
>
类似于df。assign()
(支持一次添加多个列),但能够将行传递到lambda而不是完整的数据帧中
将我的compute\u new\u columnX\u value()
函数矢量化的方法,以便它们可以像df那样用作lambda函数。assign()
希望使用它们。
到目前为止,第二种解决方案的问题是,我的一些函数的基于行的版本如下所示,我很难找到如何正确地对它们进行矢量化:
def compute_new_column1_value(row):
if row["SomeExistingColumn"] in some_dictionary:
return some_dictionary[row["SomeExistingColumn"]]
else:
return some_default_value
而不是试图将行标签引入。assign(),可以在链接之前对数据帧应用布尔掩码。将()赋值给它。下面的示例可以很容易地扩展到多个布尔条件和多个lambda,包括或不包括额外的for循环或if语句。
import pandas as pd
# Create data frame
idx = np.arange(0, 10)
rnd = pd.Series(np.random.randint(10, 20, 10))
alpha_idx = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']
df = pd.DataFrame({'idx': idx, 'A': rnd, 'B': 100})
df.index = alpha_idx
# First assign() dependent on a boolean mask
df_tmp = df[df['A'] < 15].assign(AmulB = lambda x: (x.A.mul(x.B)),
A_B = lambda x: x.B - x.A)
# Second assign() dependent on a boolean mask
df_tmp2 = df[df['A'] >= 15].assign(AmulB = lambda x: (x.A.div(x.B)),
A_B = lambda x: x.B + x.A)
# Create a new df with different lambdas combined
df_lambdas = df_tmp.append(df_tmp2)
# Sort values
df_lambdas.sort_values('idx', axis=0, inplace=True)
print(df_lambdas)
A B idx
a 19 100 0
b 17 100 1
c 16 100 2
d 13 100 3
e 15 100 4
f 10 100 5
g 16 100 6
h 15 100 7
i 13 100 8
j 10 100 9
A B idx A_B AmulB
a 19 100 0 119 0.19
b 17 100 1 117 0.17
c 16 100 2 116 0.16
d 13 100 3 87 1300.00
e 15 100 4 115 0.15
f 10 100 5 90 1000.00
g 16 100 6 116 0.16
h 15 100 7 115 0.15
i 13 100 8 87 1300.00
j 10 100 9 90 1000.00
如果您只需要检查50个条件,那么最好遍历这些条件并在块中填充单元格,而不是逐行遍历整个帧。顺便说一句assign()不仅接受lambda函数,而且代码的可读性也比我之前的建议要高得多。下面是一个修改版本,它也填充了额外的列。如果这个数据框有10000000行,我只想对A列中的10组数字范围应用不同的操作,这将是填充额外列的一种非常简洁的方法。
import pandas as pd
import numpy as np
# Create data frame
rnd = np.random.randint(1, 10, 10)
rnd2 = np.random.randint(100, 1000, 10)
df = pd.DataFrame(
{'A': rnd, 'B': rnd2, 'C': np.nan, 'D': np.nan, 'E': np.nan })
# Define different ways of filling the extra cells
def f1():
return df['A'].mul(df['B'])
def f2():
return np.log10(df['A'])
def f3():
return df['B'] - df['A']
def f4():
return df['A'].div(df['B'])
def f5():
return np.sqrt(df['B'])
def f6():
return df['A'] + df['B']
# First assign() dependent on a boolean mask
df[df['A'] < 50] = df[df['A'] < 15].assign(C = f1(), D = f2(), E = f3())
# Second assign() dependent on a boolean mask
df[df['A'] >= 50] = df[df['A'] >= 50].assign(C = f4(), D = f5(), E = f6())
print(df)
A B C D E
0 4.0 845.0 3380.0 0.602060 841
1 3.0 967.0 2901.0 0.477121 964
2 3.0 468.0 1404.0 0.477121 465
3 2.0 548.0 1096.0 0.301030 546
4 3.0 393.0 1179.0 0.477121 390
5 7.0 741.0 5187.0 0.845098 734
6 1.0 269.0 269.0 0.000000 268
7 4.0 731.0 2924.0 0.602060 727
8 4.0 193.0 772.0 0.602060 189
9 3.0 306.0 918.0 0.477121 303
您是否尝试过将列初始化为nan
,按行遍历数据框,并使用loc
赋值?
import numpy as np
import pandas as pd
df = pd.DataFrame(np.random.randint(0, 20, (10, 5)))
df[5] = np.nan
df[6] = np.nan
for i, row in df.iterrows():
df.loc[i, 5] = row[1] + row[4]
df.loc[i, 6] = row[3] * 2
print(df)
产量
0 1 2 3 4
0 17 4 3 11 10
1 16 1 14 11 16
2 4 18 12 19 7
3 11 3 7 10 5
4 11 0 10 1 17
5 5 17 10 3 8
6 0 0 7 3 6
7 7 18 18 13 8
8 16 4 12 11 16
9 13 9 15 8 19
0 1 2 3 4 5 6
0 17 4 3 11 10 14.0 22.0
1 16 1 14 11 16 17.0 22.0
2 4 18 12 19 7 25.0 38.0
3 11 3 7 10 5 8.0 20.0
4 11 0 10 1 17 17.0 2.0
5 5 17 10 3 8 25.0 6.0
6 0 0 7 3 6 6.0 6.0
7 7 18 18 13 8 26.0 26.0
8 16 4 12 11 16 20.0 22.0
9 13 9 15 8 19 28.0 16.0
那么,如何使用PySpark向现有的DataFrame添加一个新列(基于Python vector)呢?
初始数据流: 产生的数据frame: 我通常通过使用以下内容将新列“追加”到dataframe:
问题内容: 我在尝试获取另一列中的字符串值的字符计数列时遇到问题,但还没有弄清楚如何有效地做到这一点。 显然,这涉及首先创建一个null列,然后将其重写,这对我的数据集要花费很长时间。那么获得这样的东西最有效的方法是什么 我已经检查了很多,但是还无法弄清楚。 问题答案: Pandas为此使用了矢量化字符串方法:。要创建新列,您可以编写: 例如: 这应该比使用Python循环在DataFrame上循
假设我有两个表,表A和表B,它们有一对多的关系。 col1 | Col2 Col1|Col3 现在,我希望表a中有一个Col4,如果对于给定的Col1值,Col3的任何一行都为true,那么我希望表a中的Col4设置为true,否则为false。 表B上发生的所有更新都应始终更新表A中的Col4值。 使用任何oracle/PL-SQL特性都可以做到这一点吗?
几个小时以来,我一直试图找到一种方法来复制n次列,并为它们添加一个,但运气不佳。请帮帮忙! 当前数据帧: 输出:
在我的scala程序中,我有一个dataframe,其中有两列和(类型都为)。除此之外,我有一个先前定义的对象和一些方法和属性。在这里,我想要使用dataframe的当前值和中的属性向dataframe添加一个新列。 例如,如果我有下面的dataframe: 谢谢你。