Python 将函数应用于dataframe中的每两列,并用输出替换原始列
我有一个数据框,其中包含以下列中的X&Y数据:Python 将函数应用于dataframe中的每两列,并用输出替换原始列,python,pandas,dataframe,numpy,Python,Pandas,Dataframe,Numpy,我有一个数据框,其中包含以下列中的X&Y数据: df_cols = ['x1', 'y1', 'x2', 'y2', 'x3', 'y3'] np.random.seed(365) df = pd.DataFrame(np.random.randint(0,10,size=(10, 6)), columns=df_cols) x1 y1 x2 y2 x3 y3 0 2 4 1 5 2 2 1 9 8 4 0 3 3 2 7
df_cols = ['x1', 'y1', 'x2', 'y2', 'x3', 'y3']
np.random.seed(365)
df = pd.DataFrame(np.random.randint(0,10,size=(10, 6)), columns=df_cols)
x1 y1 x2 y2 x3 y3
0 2 4 1 5 2 2
1 9 8 4 0 3 3
2 7 7 7 0 8 4
3 3 2 6 2 6 8
4 9 6 1 6 5 7
5 7 6 5 9 3 8
6 7 9 9 0 1 4
7 0 9 6 5 6 9
8 5 3 2 7 9 2
9 6 6 3 7 7 1
我需要调用一个函数,该函数一次获取一个X&Y对,并返回和更新X&Y对(相同长度),然后用原始列名将该数据保存到新的数据框中,或者用新数据替换旧的X&Y数据并保留原始列名
例如,以下面的函数为例:
def samplefunc(x, y):
x = x*y
y = x/10
return x, y
# Apply function to each x & y pair
x1, y1 = samplefunc(df.x1, df.y1)
x2, y2 = samplefunc(df.x2, df.y2)
x3, y3 = samplefunc(df.x3, df.y3)
# Save new/updated x & y pairs into new dataframe, preserving the original column names
df_updated = pd.DataFrame({'x1': x1, 'y1': y1, 'x2': x2, 'y2': y2, 'x3': x3, 'y3': y3})
# Desired result:
In [36]: df_updated
Out[36]:
x1 y1 x2 y2 x3 y3
0 8 0.8 5 0.5 4 0.4
1 72 7.2 0 0.0 9 0.9
2 49 4.9 0 0.0 32 3.2
3 6 0.6 12 1.2 48 4.8
4 54 5.4 6 0.6 35 3.5
5 42 4.2 45 4.5 24 2.4
6 63 6.3 0 0.0 4 0.4
7 0 0.0 30 3.0 54 5.4
8 15 1.5 14 1.4 18 1.8
9 36 3.6 21 2.1 7 0.7
但是,对于一个庞大的数据集来说,这样做显然是非常乏味和不可能的。
我发现的类似/相关问题对数据执行简单的转换,而不是调用函数,或者它们向数据帧添加新列,而不是替换原始列
我试图将@PaulH的答案应用于我的数据集,但这两种方法都不起作用,因为目前还不清楚如何实际调用这两种方法中的函数
# Method 1
array = np.array(my_actual_df)
df_cols = my_actual_df.columns
dist = 0.04 # a parameter I need for my function
df = (
pandas.DataFrame(array, columns=df_cols)
.rename_axis(index='idx', columns='label')
.stack()
.to_frame('value')
.reset_index()
.assign(value=lambda df: numpy.select(
[df['label'].str.startswith('x'), df['label'].str.startswith('y')],
# Call the function (not working):
[df['value'], df['value']] = samplefunc(df['value'], df['value']),
))
.pivot(index='idx', columns='label', values='value')
.loc[:, df_cols]
)
# Method 2
df = (
pandas.DataFrame(array, columns=df_cols)
.pipe(lambda df: df.set_axis(df.columns.map(lambda c: (c[0], c[1])), axis='columns'))
.rename_axis(columns=['which', 'group'])
.stack(level='group')
# Call the function (not working)
.assign(df['x'], df['y'] = samplefunc(df['x'], df['y']))
.unstack(level='group')
.pipe(lambda df: df.set_axis([''.join(c) for c in df.columns], axis='columns'))
)
我需要调用的实际函数来自Arty对这个问题的回答:有几种方法可以实现这一点,具体取决于实际数据帧的构造方式 我想到的第一件事是完全堆叠数据帧并使用
numpy。选择根据标签的值计算新值。然后,可以将数据帧旋转回其原始形式:
导入numpy
进口大熊猫
df_cols=['x1','y1','x2','y2','x3','y3']
numpy.random.seed(365)
array=numpy.random.randint(0,10,size=(10,6))
df=(
pandas.DataFrame(数组,列=df_cols)
.rename_轴(index='idx',columns='label')
.stack()
.to_帧(“值”)
.reset_index()
.assign(值=λdf:numpy.select(
[df['label'].str.startswith('x'),df['label'].str.startswith('y'),
[df['value']**2,df['value']/10],
))
.pivot(index='idx',columns='label',values='value')
.loc[:,df_cols]
)
或者,您可以将列名视为层次结构,将其转换为多级索引,然后仅堆叠该索引的第二级。这样,您就得到了单独的x列和y列,可以直接显式地对其进行操作
df=(
pandas.DataFrame(数组,列=df_cols)
.pipe(lambda df:df.set_axis(df.columns.map(lambda c:(c[0],c[1])),axis='columns'))
.rename_轴(列=['哪个','组])
.stack(level='group')
.assign(x=lambda-df:df['x']**2,y=lambda-df:df['y']/10)
.unstack(level='group')
.pipe(lambda-df:df.set_轴(['''.join(c)表示df.columns中的c],axis='columns'))
)
使用切片并对这些切片应用操作
def samplefunc(x, y):
x = x**2
y = y/10
return x, y
arr = df.to_numpy().astype(object)
e_col = arr[:, ::2]
o_col = arr[:, 1::2]
e_col, o_col = samplefunc(e_col, o_col)
arr[:, ::2] = e_col
arr[:, 1::2] = o_col
out = pd.DataFrame(arr, columns=df.columns)
x1 y1 x2 y2 x3 y3
0 4 0.4 1 0.5 4 0.2
1 81 0.8 16 0.0 9 0.3
2 49 0.7 49 0.0 64 0.4
3 9 0.2 36 0.2 36 0.8
4 81 0.6 1 0.6 25 0.7
5 49 0.6 25 0.9 9 0.8
6 49 0.9 81 0.0 1 0.4
7 0 0.9 36 0.5 36 0.9
8 25 0.3 4 0.7 81 0.2
9 36 0.6 9 0.7 49 0.1
这里的新方法:
- 将列拆分为多级索引
- 做水平分组
- 修改
samplefunc
以获取数据帧:
def samplefunc(df,xcol='x',ycol='y'):
x=df[xcol]。to_numpy()
y=df[ycol]。to_numpy()
df[xcol]=x*y
df[ycol]=x/10
返回df
df=(
pandas.DataFrame(数组,列=df_cols)
.pipe(lambda df:df.set_axis(df.columns.map(lambda c:(c[0],c[1])),axis='columns'))
.rename_轴(列=['哪个','组])
.groupby(level='group',axis='columns')
.apply(samplefunc)
.pipe(lambda-df:df.set_轴(['''.join(c)表示df.columns中的c],axis='columns'))
)
我得到:
x1 y1 x2 y2 x3 y3
0 8 0.8 5 0.5 4 0.4
1 72 7.2 0 0.0 9 0.9
2 49 4.9 0 0.0 32 3.2
3 6 0.6 12 1.2 48 4.8
4 54 5.4 6 0.6 35 3.5
5 42 4.2 45 4.5 24 2.4
6 63 6.3 0 0.0 4 0.4
7 0 0.0 30 3.0 54 5.4
8 15 1.5 14 1.4 18 1.8
9 36 3.6 21 2.1 7 0.7
这回答了你的问题吗?如果函数对x和y列执行单独的操作,则可以添加一个条件来检查列名,并为x和y列选择不同的函数。这使得整个过程更加复杂easier@VirtualScooter谢谢,但它没有回答我的问题,因为它在原始数据帧中创建了一个新列,而不是用输出替换原始数据。它在添加新数据时也不会保留列名。@AmirMaleki我正在使用的实际函数需要同时使用两个x和y值作为输入,并返回两个更新的x和y值,以便在随机中添加种子,因此数据保持与您相同,我只是不确定如何在您提供的代码中包含实际调用函数。我在问题中加入了我的尝试。函数要求同时传递x&y,然后一起返回更新后的x&y数组。@CentauriAurelius我认为第二个方法是您想要的,但也不清楚如何在第二个方法中调用我的函数。我也在我的问题中加入了使用第二种方法的尝试。@CentauriAureliusresample\u euclid\u equidist
来自哪里?这是我需要应用于df的实际函数。我刚刚编辑了调用“samplefunc”的代码。您可以编辑答案来调用我提供的示例函数吗?(samplefunc)@CentauriAurelius实际上不需要重塑,编辑了答案谢谢,这对我来说更容易理解,但唯一的问题是它一次通过所有偶数列和所有奇数列。我正在使用的函数要求每次传递一个X&Y对这对于简单的示例函数很好,但我真的希望得到一个不需要更改函数的答案(即,只需在每对2列上调用函数,然后返回两列)。我担心如果我试图更改重采样欧几里德均衡器函数,我会破坏它,或者调试它会花费很长时间,因为它是如此巨大和复杂(我充其量只是一个平庸的程序员)。@CentauriAurelius我更改函数的方式只是将数据帧列解包/打包到numpy数组中。开头有两行。最后两行。
x1 y1 x2 y2 x3 y3
0 8 0.8 5 0.5 4 0.4
1 72 7.2 0 0.0 9 0.9
2 49 4.9 0 0.0 32 3.2
3 6 0.6 12 1.2 48 4.8
4 54 5.4 6 0.6 35 3.5
5 42 4.2 45 4.5 24 2.4
6 63 6.3 0 0.0 4 0.4
7 0 0.0 30 3.0 54 5.4
8 15 1.5 14 1.4 18 1.8
9 36 3.6 21 2.1 7 0.7