Pandas 数据框循环特定列的所有值
Pandas dataframe loop all values for certain column
使用 pandas 数据框假设我的数据框结构如下:
import pandas as pd
a_choise = ["True", "False", "False", "False", "True", "False", "False", "True", "True"]
b_choise = ["True", "True", "False", "False", "False", "False", "True", "True", "True"]
c_choise = ["False", "False", "True", "False", "True", "True", "False", "True", "False"]
a_n = ["a1", "a2", "a3", "a4", "a5", "a6", "a7", "a8", "a9"]
b_n = ["b1", "b2", "b3", "b4", "b5", "b6", "b7", "b8", "b9"]
c_n = ["c1", "c2", "c3", "c4", "c5", "c6", "c7", "c8", "c9"]
df = pd.DataFrame(
{"a": list(range(1, 10)), "b": list(range(11, 20)), "c": range(21, 30),
"a_Cho":a_choise, "b_Cho":b_choise, "c_Cho":c_choise,
"a_n":a_n, "b_n":b_n, "c_n":c_n}
)
a b c a_Cho b_Cho c_Cho a_n b_n c_n
0 1 11 21 True True False a1 b1 c1
1 2 12 22 False True False a2 b2 c2
2 3 13 23 False False True a3 b3 c3
3 4 14 24 False False False a4 b4 c4
4 5 15 25 True False True a5 b5 c5
5 6 16 26 False False True a6 b6 c6
6 7 17 27 False True False a7 b7 c7
7 8 18 28 True True True a8 b8 c8
8 9 19 29 True True False a9 b9 c9
我想要满足以下条件的新的 2 列 (Choise, Value)
对于“a_Cho”、“b_Cho”和“c_Cho”
中的所有值
- if "a_Cho" = true then choise = "a_n", value = a 对应"a_Cho" elif "a_Cho" = false 然后移动到下一个
- if "b_Cho" = true then choise = "b_n", value = b 对应"b_Cho" elif "b_Cho" = false 然后移动到下一个
- if "c_Cho" = true then choise = "c_n", value = c为"c_Cho"对应的值elif "c_Cho" = false 然后移动到下一个
- if "x_Cho" = false then value and choise = "Invalide"
已编辑
感谢您更新问题。经过您的编辑,我相信 .loc
会对您有所帮助。 .loc
允许我们执行“逻辑索引”,根据列相等抓取行。
例如,以下获取第 a_Cho
列等于 "True"
、
的所有行
>>> df.loc[df.a_Cho.eq('True'), ['a_n', 'a']]
a b c a_Cho b_Cho c_Cho a_n b_n c_n
0 1 11 21 True True False a1 b1 c1
4 5 15 25 True False True a5 b5 c5
7 8 18 28 True True True a8 b8 c8
8 9 19 29 True True False a9 b9 c9
我们还可以 select 使用 .loc
的列子集。
>>> df.loc[df.a_Cho.eq("True"), ["a_n", "a"]].rename(columns={"a_n": "choise", "a": "value"})
我使用 .rename()
重命名列的位置。
使用上述方法,我们可以对您陈述的每个条件执行逻辑索引,然后连接结果。
def new_col_names(x):
return {x + "_n": "choise", x: "value"}
# logical criteria
only_a = df.a_Cho.eq("True")
only_b = df.a_Cho.eq("False") & df.b_Cho.eq("True")
only_c = df.a_Cho.eq("False") & df.b_Cho.eq("False") & df.c_Cho.eq("True")
invalid = df.a_Cho.eq("False") & df.b_Cho.eq("False") & df.c_Cho.eq("False")
df_a = df.loc[only_a, ["a_n", "a"]].rename(columns=new_col_names("a"))
df_b = df.loc[only_b, ["b_n", "b"]].rename(columns=new_col_names("b"))
df_c = df.loc[only_c, ["c_n", "c"]].rename(columns=new_col_names("c"))
df_inv = df.loc[invalid].assign(choise="invalide", value="invalide").copy()
df_inv = df_inv[["choise", "value"]]
df_new = pd.concat([df_a, df_b, df_c, df_inv])
最后的 DataFrame
看起来像:
choise value
0 a1 1
4 a5 5
7 a8 8
8 a9 9
1 b2 12
6 b7 17
2 c3 23
5 c6 26
3 invalide invalide
请注意,左侧的索引值显示每个条目的原始行号。如果您不关心这些数字,您可以将 ignore_index=True
选项传递给 .concat
。
这更接近您想要的吗?
原创
您好,欢迎来到 Whosebug!我不确定我是否完全理解你的问题。例如,在您的示例代码中,您似乎没有在每次迭代中使用循环变量 x
。查看与您正在使用的结构相同的示例 DataFrame
可能会有所帮助。
我的印象是你的问题可能类似于 this question which uses pd.melt
。
您的 DataFrame
结构是否如下所示?
>>> import pandas as pd
>>> df = pd.DataFrame(
{"A": list(range(1, 10)), "B": list(range(11, 20)), "C": range(21, 30)}
)
>>> df.head()
A B C
0 1 11 21
1 2 12 22
2 3 13 23
3 4 14 24
4 5 15 25
5 6 16 26
6 7 17 27
7 8 18 28
8 9 19 29
如果是这样,您可以使用 pd.melt
将其重组为具有两列,一个“列名”列和一个“列值”列,如您在问题中所述。
上述示例 DataFrame
的命令和输出为:
>>> pd.melt(df, value_vars=['A', 'B', 'C'])
variable value
0 A 1
1 A 2
2 A 3
3 A 4
4 A 5
5 A 6
6 A 7
7 A 8
8 A 9
9 B 11
10 B 12
11 B 13
12 B 14
13 B 15
14 B 16
15 B 17
16 B 18
17 B 19
18 C 21
19 C 22
20 C 23
21 C 24
22 C 25
23 C 26
24 C 27
25 C 28
26 C 29
这和你问的类似吗?如果没有,您能否提供一个您正在使用的 DataFrame
的示例以及您希望最终结果是什么样子的示例?它可以是一个简化的或“模拟”的例子。
使用 pandas 数据框假设我的数据框结构如下:
import pandas as pd
a_choise = ["True", "False", "False", "False", "True", "False", "False", "True", "True"]
b_choise = ["True", "True", "False", "False", "False", "False", "True", "True", "True"]
c_choise = ["False", "False", "True", "False", "True", "True", "False", "True", "False"]
a_n = ["a1", "a2", "a3", "a4", "a5", "a6", "a7", "a8", "a9"]
b_n = ["b1", "b2", "b3", "b4", "b5", "b6", "b7", "b8", "b9"]
c_n = ["c1", "c2", "c3", "c4", "c5", "c6", "c7", "c8", "c9"]
df = pd.DataFrame(
{"a": list(range(1, 10)), "b": list(range(11, 20)), "c": range(21, 30),
"a_Cho":a_choise, "b_Cho":b_choise, "c_Cho":c_choise,
"a_n":a_n, "b_n":b_n, "c_n":c_n}
)
a b c a_Cho b_Cho c_Cho a_n b_n c_n
0 1 11 21 True True False a1 b1 c1
1 2 12 22 False True False a2 b2 c2
2 3 13 23 False False True a3 b3 c3
3 4 14 24 False False False a4 b4 c4
4 5 15 25 True False True a5 b5 c5
5 6 16 26 False False True a6 b6 c6
6 7 17 27 False True False a7 b7 c7
7 8 18 28 True True True a8 b8 c8
8 9 19 29 True True False a9 b9 c9
我想要满足以下条件的新的 2 列 (Choise, Value) 对于“a_Cho”、“b_Cho”和“c_Cho”
中的所有值- if "a_Cho" = true then choise = "a_n", value = a 对应"a_Cho" elif "a_Cho" = false 然后移动到下一个
- if "b_Cho" = true then choise = "b_n", value = b 对应"b_Cho" elif "b_Cho" = false 然后移动到下一个
- if "c_Cho" = true then choise = "c_n", value = c为"c_Cho"对应的值elif "c_Cho" = false 然后移动到下一个
- if "x_Cho" = false then value and choise = "Invalide"
已编辑
感谢您更新问题。经过您的编辑,我相信 .loc
会对您有所帮助。 .loc
允许我们执行“逻辑索引”,根据列相等抓取行。
例如,以下获取第 a_Cho
列等于 "True"
、
>>> df.loc[df.a_Cho.eq('True'), ['a_n', 'a']]
a b c a_Cho b_Cho c_Cho a_n b_n c_n
0 1 11 21 True True False a1 b1 c1
4 5 15 25 True False True a5 b5 c5
7 8 18 28 True True True a8 b8 c8
8 9 19 29 True True False a9 b9 c9
我们还可以 select 使用 .loc
的列子集。
>>> df.loc[df.a_Cho.eq("True"), ["a_n", "a"]].rename(columns={"a_n": "choise", "a": "value"})
我使用 .rename()
重命名列的位置。
使用上述方法,我们可以对您陈述的每个条件执行逻辑索引,然后连接结果。
def new_col_names(x):
return {x + "_n": "choise", x: "value"}
# logical criteria
only_a = df.a_Cho.eq("True")
only_b = df.a_Cho.eq("False") & df.b_Cho.eq("True")
only_c = df.a_Cho.eq("False") & df.b_Cho.eq("False") & df.c_Cho.eq("True")
invalid = df.a_Cho.eq("False") & df.b_Cho.eq("False") & df.c_Cho.eq("False")
df_a = df.loc[only_a, ["a_n", "a"]].rename(columns=new_col_names("a"))
df_b = df.loc[only_b, ["b_n", "b"]].rename(columns=new_col_names("b"))
df_c = df.loc[only_c, ["c_n", "c"]].rename(columns=new_col_names("c"))
df_inv = df.loc[invalid].assign(choise="invalide", value="invalide").copy()
df_inv = df_inv[["choise", "value"]]
df_new = pd.concat([df_a, df_b, df_c, df_inv])
最后的 DataFrame
看起来像:
choise value
0 a1 1
4 a5 5
7 a8 8
8 a9 9
1 b2 12
6 b7 17
2 c3 23
5 c6 26
3 invalide invalide
请注意,左侧的索引值显示每个条目的原始行号。如果您不关心这些数字,您可以将 ignore_index=True
选项传递给 .concat
。
这更接近您想要的吗?
原创
您好,欢迎来到 Whosebug!我不确定我是否完全理解你的问题。例如,在您的示例代码中,您似乎没有在每次迭代中使用循环变量 x
。查看与您正在使用的结构相同的示例 DataFrame
可能会有所帮助。
我的印象是你的问题可能类似于 this question which uses pd.melt
。
您的 DataFrame
结构是否如下所示?
>>> import pandas as pd
>>> df = pd.DataFrame(
{"A": list(range(1, 10)), "B": list(range(11, 20)), "C": range(21, 30)}
)
>>> df.head()
A B C
0 1 11 21
1 2 12 22
2 3 13 23
3 4 14 24
4 5 15 25
5 6 16 26
6 7 17 27
7 8 18 28
8 9 19 29
如果是这样,您可以使用 pd.melt
将其重组为具有两列,一个“列名”列和一个“列值”列,如您在问题中所述。
上述示例 DataFrame
的命令和输出为:
>>> pd.melt(df, value_vars=['A', 'B', 'C'])
variable value
0 A 1
1 A 2
2 A 3
3 A 4
4 A 5
5 A 6
6 A 7
7 A 8
8 A 9
9 B 11
10 B 12
11 B 13
12 B 14
13 B 15
14 B 16
15 B 17
16 B 18
17 B 19
18 C 21
19 C 22
20 C 23
21 C 24
22 C 25
23 C 26
24 C 27
25 C 28
26 C 29
这和你问的类似吗?如果没有,您能否提供一个您正在使用的 DataFrame
的示例以及您希望最终结果是什么样子的示例?它可以是一个简化的或“模拟”的例子。