我有一个包含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'))
)