R/Python 中数据框的矩阵
Matrix from dataframe in R/Python
我有一个这样的数据框:
如果具有该 ID 的人拥有该水果,则该值为 1,否则为 0。ID 列是主键。
ID
Apple
Orange
Pear
Grapes
E1
1
0
1
1
E2
0
0
1
0
E3
0
1
1
0
E4
1
1
0
0
E5
1
0
0
1
我想要一个像这样的矩阵输出。这是同时拥有 i 和 j 个水果的人数。其中 i 和 j 都相同,例如:cell apple x apple,我们正在查看至少拥有一个 apple apple 的所有人的数量。在这里,有 3 个人有苹果,所以值为 3。同样,我们只有一个人同时有苹果和橙子 (E4),所以在 (orange x apple) 和 (apple x orange) 单元格中计数都是 1。我们在上面的数据框中有 2 个人同时拥有葡萄和苹果(E1 和 E5),因此该单元格中的值为 2.
编辑:我想要这样的输出
Apple
Orange
Pear
Grapes
Apple
3
1
1
2
Orange
1
2
1
0
Pear
1
1
3
1
Grapes
2
0
1
2
我是 R 和 Python 的新手,不知道如何实现。 R 或 Python 中的任何帮助将不胜感激!如果有任何不清楚或遗漏的内容,请随时提出问题。谢谢!
这里是 Python3 和 itertools.permutations
的例子:
import itertools
import pandas as pd
# Create original dataframe
columns = ['ID', 'Apple', 'Orange', 'Pear', 'Grapes']
rows = [
['E1', 1, 0, 1, 1],
['E2', 0, 0, 1, 0],
['E3', 0, 1, 1, 0],
['E4', 1, 1, 0, 0],
['E5', 1, 0, 0, 1],
]
df = pd.DataFrame(rows, columns=columns)
# Count values of resulting matrix
def get_ones_indexes(els):
for i, el in enumerate(els):
if el == 1:
yield i
res_n = len(df.columns) - 1
res = [[0] * res_n for _ in range(res_n)]
for _, row in df.drop('ID', axis=1).iterrows():
indexes = list(get_ones_indexes(row.to_list()))
if len(indexes) == 1:
idx = indexes[0]
res[idx][idx] += 1
else:
for i, j in itertools.permutations(indexes, 2):
res[i][j] += 1
# Convert resultinng matrix to dataframe
_, *fruit_cols = df.columns
res_df = pd.DataFrame(res, index=fruit_cols, columns=fruit_cols)
print(res_df)
# Apple Orange Pear Grapes
# Apple 0 1 1 2
# Orange 1 0 1 0
# Pear 1 1 1 1
# Grapes 2 0 1 0
这里有一个 tidyverse
R 选项:
library(tidyverse)
data %>%
pivot_longer(-ID) %>%
filter(value > 0) %>%
select(-value) %>%
group_by(ID) %>%
nest() %>%
mutate(data = map(data, ~ expand.grid(.x$name, .x$name))) %>%
unnest(data) %>%
group_by(Var1, Var2) %>%
summarise(n = n(), .groups = "drop") %>%
filter(Var1 != Var2) %>%
pivot_wider(names_from = Var1, values_from = n, values_fill = 0)
## A tibble: 4 x 5
# Var2 Apple Pear Grapes Orange
# <fct> <int> <int> <int> <int>
#1 Pear 1 0 1 1
#2 Grapes 2 1 0 0
#3 Orange 1 1 0 0
#4 Apple 0 1 2 1
想法是使用expand.grid
生成所有成对组合。剩下的就是计算出现次数和重塑。 Re-order 根据需要行和列。
PS。我应该指出,结果与预期输出略有不同。例如,我不明白为什么 (Pear, Pear) = 1。我认为这是错误的。由于您要求 co-occurrences,因此所有对角线元素都应为零。
示例数据
data <- read.table(text = "ID Apple Orange Pear Grapes
E1 1 0 1 1
E2 0 0 1 0
E3 0 1 1 0
E4 1 1 0 0
E5 1 0 0 1", header = T)
我有一个这样的数据框: 如果具有该 ID 的人拥有该水果,则该值为 1,否则为 0。ID 列是主键。
ID | Apple | Orange | Pear | Grapes |
---|---|---|---|---|
E1 | 1 | 0 | 1 | 1 |
E2 | 0 | 0 | 1 | 0 |
E3 | 0 | 1 | 1 | 0 |
E4 | 1 | 1 | 0 | 0 |
E5 | 1 | 0 | 0 | 1 |
我想要一个像这样的矩阵输出。这是同时拥有 i 和 j 个水果的人数。其中 i 和 j 都相同,例如:cell apple x apple,我们正在查看至少拥有一个 apple apple 的所有人的数量。在这里,有 3 个人有苹果,所以值为 3。同样,我们只有一个人同时有苹果和橙子 (E4),所以在 (orange x apple) 和 (apple x orange) 单元格中计数都是 1。我们在上面的数据框中有 2 个人同时拥有葡萄和苹果(E1 和 E5),因此该单元格中的值为 2.
编辑:我想要这样的输出
Apple | Orange | Pear | Grapes | |
---|---|---|---|---|
Apple | 3 | 1 | 1 | 2 |
Orange | 1 | 2 | 1 | 0 |
Pear | 1 | 1 | 3 | 1 |
Grapes | 2 | 0 | 1 | 2 |
我是 R 和 Python 的新手,不知道如何实现。 R 或 Python 中的任何帮助将不胜感激!如果有任何不清楚或遗漏的内容,请随时提出问题。谢谢!
这里是 Python3 和 itertools.permutations
的例子:
import itertools
import pandas as pd
# Create original dataframe
columns = ['ID', 'Apple', 'Orange', 'Pear', 'Grapes']
rows = [
['E1', 1, 0, 1, 1],
['E2', 0, 0, 1, 0],
['E3', 0, 1, 1, 0],
['E4', 1, 1, 0, 0],
['E5', 1, 0, 0, 1],
]
df = pd.DataFrame(rows, columns=columns)
# Count values of resulting matrix
def get_ones_indexes(els):
for i, el in enumerate(els):
if el == 1:
yield i
res_n = len(df.columns) - 1
res = [[0] * res_n for _ in range(res_n)]
for _, row in df.drop('ID', axis=1).iterrows():
indexes = list(get_ones_indexes(row.to_list()))
if len(indexes) == 1:
idx = indexes[0]
res[idx][idx] += 1
else:
for i, j in itertools.permutations(indexes, 2):
res[i][j] += 1
# Convert resultinng matrix to dataframe
_, *fruit_cols = df.columns
res_df = pd.DataFrame(res, index=fruit_cols, columns=fruit_cols)
print(res_df)
# Apple Orange Pear Grapes
# Apple 0 1 1 2
# Orange 1 0 1 0
# Pear 1 1 1 1
# Grapes 2 0 1 0
这里有一个 tidyverse
R 选项:
library(tidyverse)
data %>%
pivot_longer(-ID) %>%
filter(value > 0) %>%
select(-value) %>%
group_by(ID) %>%
nest() %>%
mutate(data = map(data, ~ expand.grid(.x$name, .x$name))) %>%
unnest(data) %>%
group_by(Var1, Var2) %>%
summarise(n = n(), .groups = "drop") %>%
filter(Var1 != Var2) %>%
pivot_wider(names_from = Var1, values_from = n, values_fill = 0)
## A tibble: 4 x 5
# Var2 Apple Pear Grapes Orange
# <fct> <int> <int> <int> <int>
#1 Pear 1 0 1 1
#2 Grapes 2 1 0 0
#3 Orange 1 1 0 0
#4 Apple 0 1 2 1
想法是使用expand.grid
生成所有成对组合。剩下的就是计算出现次数和重塑。 Re-order 根据需要行和列。
PS。我应该指出,结果与预期输出略有不同。例如,我不明白为什么 (Pear, Pear) = 1。我认为这是错误的。由于您要求 co-occurrences,因此所有对角线元素都应为零。
示例数据
data <- read.table(text = "ID Apple Orange Pear Grapes
E1 1 0 1 1
E2 0 0 1 0
E3 0 1 1 0
E4 1 1 0 0
E5 1 0 0 1", header = T)