我有一个数据框需要堆叠、融合或旋转。对于每所学校,我需要为每个容量创建一个新行,以及一个新的级别列。级别取决于容量是否 > 0。还应包括城市列:
data = pd.DataFrame({'school_name': {0: 'a', 1: 'b', 2: 'c'},
'primary': {0: 1, 1: 3, 2: 0},
'secondary': {0: 2, 1: 0, 2: 6},
'tertiary': {0:3, 1:6, 2:0},
'city': {0:'Bangkok', 1:'Frankfurt', 2:'Tel Aviv'}})
data
school_name primary secondary tertiary city
0 a 1 2 3 Bangkok
1 b 3 0 6 Frankfurt
2 c 0 6 0 Tel Aviv
想要的结果:
school_name levels capacity city
0 a primary 1 Bangkok
1 a secondary 2 Bangkok
2 a tertiary 3 Bangkok
3 b primary 3 Frankfurt
4 b tertiary 6 Frankfurt
5 c secondary 6 Tel Aviv
答案 0 :(得分:2)
让我们 stack
在屏蔽 0
、primary
和 secondary
列中的 tertiary
值后重塑数据框:
df = data.set_index(['school_name', 'city'])
df = df[df.ne(0)].stack().reset_index(name='capacity')\
.rename(columns={'level_2': 'levels'})
>>> df
school_name city levels capacity
0 a Bangkok primary 1.0
1 a Bangkok secondary 2.0
2 a Bangkok tertiary 3.0
3 b Frankfurt primary 3.0
4 b Frankfurt tertiary 6.0
5 c Tel Aviv secondary 6.0
答案 1 :(得分:2)
在过滤大于 0 的行之前,您可以使用 pivot_longer 中的 pyjanitor 来重塑数据:
import janitor
(df
.pivot_longer(index=['school_name', 'city'],
names_to=("levels", ".value"),
names_sep="_")
.query("capacity > 0")
)
school_name city levels capacity
0 a Bangkok primary 1
1 b Frankfurt primary 3
3 a Bangkok secondary 2
5 c Tel Aviv secondary 6
6 a Bangkok tertiary 3
7 b Frankfurt tertiary 6
您也可以使用熊猫的wide_to_long:
temp = df.rename(columns= lambda x: "_".join(x.split("_")[::-1])
if 'capacity' in x
else x)
(pd.wide_to_long(temp,
'capacity',
['school_name', 'city'],
"levels",
"_",
".+")
.query('capacity > 0').reset_index()
)
school_name city levels capacity
0 a Bangkok primary 1
1 a Bangkok secondary 2
2 a Bangkok tertiary 3
3 b Frankfurt primary 3
4 b Frankfurt tertiary 6
5 c Tel Aviv secondary 6
您的问题已被编辑,所以这个答案应该足够了:
(data.melt(['school_name', 'city'],
var_name='levels',
value_name='capacity')
.query('capacity > 0'))
school_name city levels capacity
0 a Bangkok primary 1
1 b Frankfurt primary 3
3 a Bangkok secondary 2
5 c Tel Aviv secondary 6
6 a Bangkok tertiary 3
7 b Frankfurt tertiary 6
答案 2 :(得分:2)
我会用 nan 替换 0 值,因为我知道这意味着该功能不存在
data2 = data.replace(0, np.nan)
然后融化我认为是你需要的。 (并删除 nan 值)
data2.melt(id_vars= ['school_name', 'city'], value_vars=['primary', 'secondary', 'tertiary']).dropna()
school_name city variable value
0 a Bangkok primary 1.0
1 b Frankfurt primary 3.0
3 a Bangkok secondary 2.0
5 c Tel Aviv secondary 6.0
6 a Bangkok tertiary 3.0
7 b Frankfurt tertiary 6.0
如果您不喜欢索引,请重置它们
data2.melt(id_vars= ['school_name', 'city'], value_vars=['primary', 'secondary', 'tertiary']).dropna().reset_index()
答案 3 :(得分:0)
# keep columns in index
data = data.set_index(["school_name","city"])
# remaining columns, name the index
data.columns.set_names("levels",inplace=True)
# simple stack and reset index
data.stack().reset_index()
学校名称 | 城市 | levels | 0 | |
---|---|---|---|---|
0 | a | 曼谷 | 主要 | 1 |
1 | a | 曼谷 | 次要 | 2 |
2 | a | 曼谷 | 第三级 | 3 |
3 | b | 法兰克福 | 主要 | 3 |
4 | b | 法兰克福 | 次要 | 0 |
5 | b | 法兰克福 | 第三级 | 6 |
6 | c | 特拉维夫 | 主要 | 0 |
7 | c | 特拉维夫 | 次要 | 6 |
8 | c | 特拉维夫 | 第三级 | 0 |