从 Pandas groupby 对象中收集系列
Collecting series from Pandas groupby object
我正在处理如下国际象棋结果的数据框
Opponent Date Time Result
0 Hikaru 2020.03.02 01:22:54 1
1 Hikaru 2020.03.02 01:22:58 0.5
2 Hikaru 2020.03.03 01:18:17 1
3 Hikaru 2020.03.03 01:19:54 0
4 Hikaru 2020.03.03 01:19:45 1
5 Hikaru 2020.03.03 02:15:23 0.5
6 Anish 2020.03.03 02:21:25 0.5
7 Anish 2020.03.03 02:21:29 0
8 Anish 2020.03.04 15:45:12 1
9 Anish 2020.03.04 15:48:11 0.5
10 Anish 2020.03.04 16:05:01 0.5
现在我想 (1) 按对手分组,(2) 按日期分组(在对手内),(3) 列出每个结果的计数,(4) 给出获得的结果的顺序.前 3 个可以用 pd.crosstab
获得,例如- 一个完整的例子 -
import pandas as pd
d = {'Opponent': ['Hikaru']*6 + ['Anish']*5,
'Date': ['2020.03.02']*2 + ['2020.03.03']*6 + ['2020.03.04']*3,
'Time': ['01:22:54', '01:22:58', '01:18:17', '01:19:54', '01:19:45', '02:15:23', '02:21:25', '02:21:29', '15:45:12', '15:48:11', '16:05:01'],
'Result': ['1', '0.5', '1', '0', '1', '0.5', '0.5', '0', '1', '0.5', '0.5']}
df = pd.DataFrame(data = d)
pd.crosstab([df['Opponent'], df['Date']],
df['Result'])
我想要的是与最后一个 pd.crosstab
相同的输出,但添加了一个列,显示了当天两位玩家之间的比赛结果顺序(按时间排序),按时间排序。理想情况下,我希望 '1's 作为 'W',0.5s 作为 'D',0s 作为 'L' 和列中的单个长字符串。
期望的输出:
Result 0 0.5 1 result_seq
Opponent Date
Anish 2020.03.03 1 1 0 DL
2020.03.04 0 2 1 WDD
Hikaru 2020.03.02 0 1 1 WD
2020.03.03 1 1 2 WWLD
请注意,在原始数据框中,不保证 games/results 按时间顺序列出;在原始数据框中,每个变量的数据类型都是 str
我想在最终输出中保持这种方式(例如 Results
应该保持为 '1', '0', ' 0.5' 字符串,而不是 '1.0'、'0.5、'0.0',Date
s 最终应该是字符串;只有实际结果计数可以而且大概是整数)。
我的想法:我想按时间排序,然后将专栏作为 pandas 系列。问题是如何在按对手和日期分组的同时(即在之后)执行此操作。
如果你有这个df
:
Opponent Date Time Result
0 Hikaru 2020.03.02 01:22:54 1.0
1 Hikaru 2020.03.02 01:22:58 0.5
2 Hikaru 2020.03.03 01:18:17 0.0
3 Hikaru 2020.03.03 01:19:45 1.0
4 Hikaru 2020.03.03 01:19:54 1.0
5 Hikaru 2020.03.03 02:15:23 0.5
6 Anish 2020.03.03 02:21:25 0.5
7 Anish 2020.03.03 02:21:29 0.0
8 Anish 2020.03.04 15:45:12 1.0
9 Anish 2020.03.04 15:48:11 0.5
10 Anish 2020.03.04 16:05:01 0.5
然后你可以使用.pivot_table()
得到你的结果:
df_out = df.pivot_table(
index=["Opponent", "Date"],
columns="Result",
aggfunc="size",
fill_value=0,
).rename(columns={0.0: "0", 1.0: "1"})
df_out["result_seq"] = df.groupby(["Opponent", "Date"])["Result"].apply(
lambda x: "".join({0: "L", 1: "W", 0.5: "D"}[v] for v in x)
)
print(df_out)
打印:
Result 0 0.5 1 result_seq
Opponent Date
Anish 2020.03.03 1 1 0 DL
2020.03.04 0 2 1 WDD
Hikaru 2020.03.02 0 1 1 WD
2020.03.03 1 1 2 LWWD
编辑:按时间对值进行排序:
df["tmp"] = pd.to_datetime(df.Date + " " + df.Time)
df = df.sort_values(by="tmp").drop(columns="tmp")
df_out = df.pivot_table(
index=["Opponent", "Date"],
columns="Result",
aggfunc="size",
fill_value=0,
).rename(columns={0.0: "0", 1.0: "1"})
df_out["result_seq"] = df.groupby(["Opponent", "Date"])["Result"].apply(
lambda x: "".join({0: "L", 1: "W", 0.5: "D"}[v] for v in x)
)
print(df_out)
打印:
Result 0 0.5 1 result_seq
Opponent Date
Anish 2020.03.03 1 1 0 DL
2020.03.04 0 2 1 WDD
Hikaru 2020.03.02 0 1 1 WD
2020.03.03 1 1 2 WWLD
你走在正确的轨道上。只需重命名带有所需标签的列:
df1=pd.crosstab([df['Opponent'], df['Date']],
df['Result']).reset_index().rename(columns={1.0:'W',0.5:'D',0.0:'L'})
创建新列,在其中根据列值连接相关列的一部分
df1['result_seq'] = df1.iloc[:,2:].mul(df1.iloc[:,2:].columns.values).sum(axis=1)
Result Opponent Date L D W result_seq
0 Anish 2020.03.03 1 1 0 LD
1 Anish 2020.03.04 0 2 1 DDW
2 Hikaru 2020.03.02 0 1 1 DW
3 Hikaru 2020.03.03 1 1 2 LDWW
我正在处理如下国际象棋结果的数据框
Opponent Date Time Result
0 Hikaru 2020.03.02 01:22:54 1
1 Hikaru 2020.03.02 01:22:58 0.5
2 Hikaru 2020.03.03 01:18:17 1
3 Hikaru 2020.03.03 01:19:54 0
4 Hikaru 2020.03.03 01:19:45 1
5 Hikaru 2020.03.03 02:15:23 0.5
6 Anish 2020.03.03 02:21:25 0.5
7 Anish 2020.03.03 02:21:29 0
8 Anish 2020.03.04 15:45:12 1
9 Anish 2020.03.04 15:48:11 0.5
10 Anish 2020.03.04 16:05:01 0.5
现在我想 (1) 按对手分组,(2) 按日期分组(在对手内),(3) 列出每个结果的计数,(4) 给出获得的结果的顺序.前 3 个可以用 pd.crosstab
获得,例如- 一个完整的例子 -
import pandas as pd
d = {'Opponent': ['Hikaru']*6 + ['Anish']*5,
'Date': ['2020.03.02']*2 + ['2020.03.03']*6 + ['2020.03.04']*3,
'Time': ['01:22:54', '01:22:58', '01:18:17', '01:19:54', '01:19:45', '02:15:23', '02:21:25', '02:21:29', '15:45:12', '15:48:11', '16:05:01'],
'Result': ['1', '0.5', '1', '0', '1', '0.5', '0.5', '0', '1', '0.5', '0.5']}
df = pd.DataFrame(data = d)
pd.crosstab([df['Opponent'], df['Date']],
df['Result'])
我想要的是与最后一个 pd.crosstab
相同的输出,但添加了一个列,显示了当天两位玩家之间的比赛结果顺序(按时间排序),按时间排序。理想情况下,我希望 '1's 作为 'W',0.5s 作为 'D',0s 作为 'L' 和列中的单个长字符串。
期望的输出:
Result 0 0.5 1 result_seq
Opponent Date
Anish 2020.03.03 1 1 0 DL
2020.03.04 0 2 1 WDD
Hikaru 2020.03.02 0 1 1 WD
2020.03.03 1 1 2 WWLD
请注意,在原始数据框中,不保证 games/results 按时间顺序列出;在原始数据框中,每个变量的数据类型都是 str
我想在最终输出中保持这种方式(例如 Results
应该保持为 '1', '0', ' 0.5' 字符串,而不是 '1.0'、'0.5、'0.0',Date
s 最终应该是字符串;只有实际结果计数可以而且大概是整数)。
我的想法:我想按时间排序,然后将专栏作为 pandas 系列。问题是如何在按对手和日期分组的同时(即在之后)执行此操作。
如果你有这个df
:
Opponent Date Time Result
0 Hikaru 2020.03.02 01:22:54 1.0
1 Hikaru 2020.03.02 01:22:58 0.5
2 Hikaru 2020.03.03 01:18:17 0.0
3 Hikaru 2020.03.03 01:19:45 1.0
4 Hikaru 2020.03.03 01:19:54 1.0
5 Hikaru 2020.03.03 02:15:23 0.5
6 Anish 2020.03.03 02:21:25 0.5
7 Anish 2020.03.03 02:21:29 0.0
8 Anish 2020.03.04 15:45:12 1.0
9 Anish 2020.03.04 15:48:11 0.5
10 Anish 2020.03.04 16:05:01 0.5
然后你可以使用.pivot_table()
得到你的结果:
df_out = df.pivot_table(
index=["Opponent", "Date"],
columns="Result",
aggfunc="size",
fill_value=0,
).rename(columns={0.0: "0", 1.0: "1"})
df_out["result_seq"] = df.groupby(["Opponent", "Date"])["Result"].apply(
lambda x: "".join({0: "L", 1: "W", 0.5: "D"}[v] for v in x)
)
print(df_out)
打印:
Result 0 0.5 1 result_seq
Opponent Date
Anish 2020.03.03 1 1 0 DL
2020.03.04 0 2 1 WDD
Hikaru 2020.03.02 0 1 1 WD
2020.03.03 1 1 2 LWWD
编辑:按时间对值进行排序:
df["tmp"] = pd.to_datetime(df.Date + " " + df.Time)
df = df.sort_values(by="tmp").drop(columns="tmp")
df_out = df.pivot_table(
index=["Opponent", "Date"],
columns="Result",
aggfunc="size",
fill_value=0,
).rename(columns={0.0: "0", 1.0: "1"})
df_out["result_seq"] = df.groupby(["Opponent", "Date"])["Result"].apply(
lambda x: "".join({0: "L", 1: "W", 0.5: "D"}[v] for v in x)
)
print(df_out)
打印:
Result 0 0.5 1 result_seq
Opponent Date
Anish 2020.03.03 1 1 0 DL
2020.03.04 0 2 1 WDD
Hikaru 2020.03.02 0 1 1 WD
2020.03.03 1 1 2 WWLD
你走在正确的轨道上。只需重命名带有所需标签的列:
df1=pd.crosstab([df['Opponent'], df['Date']],
df['Result']).reset_index().rename(columns={1.0:'W',0.5:'D',0.0:'L'})
创建新列,在其中根据列值连接相关列的一部分
df1['result_seq'] = df1.iloc[:,2:].mul(df1.iloc[:,2:].columns.values).sum(axis=1)
Result Opponent Date L D W result_seq
0 Anish 2020.03.03 1 1 0 LD
1 Anish 2020.03.04 0 2 1 DDW
2 Hikaru 2020.03.02 0 1 1 DW
3 Hikaru 2020.03.03 1 1 2 LDWW