对数据框中的每两列应用函数,并将原始列替换为输出



我有一个包含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   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 &并返回并更新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对这个问题的回答:重新采样轨迹,使每个样本具有相等的欧几里得距离

使用切片并在这些切片上应用操作。

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
return df
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'])
.groupby(level='group', axis='columns')
.apply(samplefunc)
.pipe(lambda df: df.set_axis([''.join(c) for c in df.columns], 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

有几种方法可以做到这一点,这取决于您的实际数据框架是如何构建的。

我想到的第一件事是完全堆叠数据帧,并使用numpy.select来计算基于标签值的新值。然后,您可以将数据框转回其原始形式:

import numpy
import pandas
df_cols = ['x1', 'y1', 'x2', 'y2', 'x3', 'y3']

numpy.random.seed(365)
array = numpy.random.randint(0, 10, size=(10, 6))
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')],
[df['value'] ** 2, df['value'] / 10],
))
.pivot(index='idx', columns='label', values='value')
.loc[:, df_cols]
)
label    x1   y1    x2   y2    x3   y3
idx                                   
0       4.0  0.4   1.0  0.5   4.0  0.2
1      81.0  0.8  16.0  0.0   9.0  0.3
2      49.0  0.7  49.0  0.0  64.0  0.4
3       9.0  0.2  36.0  0.2  36.0  0.8
4      81.0  0.6   1.0  0.6  25.0  0.7
5      49.0  0.6  25.0  0.9   9.0  0.8
6      49.0  0.9  81.0  0.0   1.0  0.4
7       0.0  0.9  36.0  0.5  36.0  0.9
8      25.0  0.3   4.0  0.7  81.0  0.2
9      36.0  0.6   9.0  0.7  49.0  0.1

或者,您可以将列名视为层次结构,将其转换为多级索引,然后仅堆叠该索引的第二级。这样,你就得到了单独的x列和y列,你可以直接和显式地操作

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')
.assign(x=lambda df: df['x'] ** 2, y=lambda df: df['y'] / 10)
.unstack(level='group')
.pipe(lambda df: df.set_axis([''.join(c) for c in df.columns], axis='columns'))
)

相关内容

  • 没有找到相关文章

最新更新