pmap不跨数据帧行映射

时间:2018-07-17 01:36:41

标签: r tidyverse purrr

我正在尝试将函数映射到包含在其中的多个输入 使用#include <winsock2.h> #include <windows.h> #pragma comment(lib,"ws2_32.lib") #include <iostream> #include <thread> #include <string> #include <cstdint> #include <stdexcept> #include <limits> #include <algorithm> // The below variables are used to let the client wait for the server // port to be opened. If you don't want to use these, especially if the // client and server are ever run on different machines, you can omit // these and instead just have the client call connect() in a loop // until successful... // #include <mutex> #include <condition_variable> #include <chrono> static std::condition_variable server_cv; static std::mutex server_mtx; static bool server_is_listening = false; // static const int num_threads = 2; static const u_short server_port = 1111; class winsock_error : public std::runtime_error { public: int errCode; std::string funcName; winsock_error(int errCode, const char *funcName) : std::runtime_error("WinSock error"), errCode(errCode), funcName(funcName) {} }; void WinSockError(const char *funcName, int errCode = WSAGetLastError()) { throw winsock_error(errCode, funcName); } class connection_closed : public std::runtime_error { public: connection_closed() : std::runtime_error("Connection closed") {} }; class socket_ptr { public: socket_ptr(SOCKET s) : m_sckt(s) {} socket_ptr(const socket_ptr &) = delete; socket_ptr(socket_ptr &&src) : m_sckt(src.m_sckt) { src.m_sckt = INVALID_SOCKET; } ~socket_ptr() { if (m_sckt != INVALID_SOCKET) closesocket(m_sckt); } socket_ptr& operator=(const socket_ptr &) = delete; socket_ptr& operator=(socket_ptr &&rhs) { m_sckt = rhs.m_sckt; rhs.m_sckt = INVALID_SOCKET; return *this; } operator SOCKET() { return m_sckt; } bool operator!() const { return (m_sckt == INVALID_SOCKET); } private: SOCKET m_sckt; } template <typename T> T LimitBufferSize(size_t size) { return (T) std::min(size, (size_t) std::numeric_limits<T>::max()); } void sendRaw(SOCKET sckt, const void *buffer, size_t buflen) { const char *ptr = static_cast<const char*>(buffer); while (buflen > 0) { int numToSend = LimitBufferSize<int>(buflen); int numSent = ::send(sckt, ptr, numToSend, 0); if (numSent == SOCKET_ERROR) WinSockError("send"); ptr += numSent; buflen -= numSent; } } void recvRaw(SOCKET sckt, void *buffer, size_t buflen) { char *ptr = static_cast<char*>(buffer); while (buflen > 0) { int numToRecv = LimitBufferSize<int>(buflen); int numRecvd = ::recv(sckt, ptr, numToRecv, 0); if (numRecvd == SOCKET_ERROR) WinSockError("recv"); if (numRecvd == 0) throw connection_closed(); ptr += numRecvd; buflen -= numRecvd; } } void sendStr(SOCKET sckt, const std::string &str) { uint32_t len = LimitBufferSize<uint32_t>(str.size()); uint32_t tmp = htonl(len); sendRaw(sckt, &tmp, sizeof(tmp)); if (len > 0) sendRaw(sckt, str.c_str(), len); } std::string recvStr(SOCKET sckt) { std::string str; uint32_t len; recvRaw(sckt, &len, sizeof(len)); len = ntohl(len); if (len > 0) { str.resize(len); recvRaw(sckt, &str[0], len); } return str; } void server_thread() { std::cout << "[Server] Starting ..." << std::endl; try { socket_ptr sListen(::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)); if (!sListen) WinSockError("socket"); SOCKADDR_IN addr = {}; addr.sin_family = AF_INET; addr.sin_addr.s_addr = ::inet_addr("127.0.0.1"); addr.sin_port = ::htons(server_port); int addrlen = sizeof(addr); if (::bind(sListen, (SOCKADDR*)&addr, sizeof(addr)) == SOCKET_ERROR) WinSockError("bind"); if (::listen(sListen, 1) == SOCKET_ERROR) WinSockError("listen"); // this is optional... { std::unique_lock<std::mutex> lk(server_mtx); server_is_listening = true; } server_cv.notify_all(); // std::cout << "[Server] Listening for Client ..." << std::endl; socket_ptr newConnection(::accept(sListen, (SOCKADDR*)&addr, &addrlen)); if (!newConnection) WinSockError("accept"); std::cout << "[Server] Client Connected!" << std::endl; try { std::string a; while (std::cin >> a) sendStr(newConnection, a); } catch (const connection_closed &) { } catch (const winsock_error &e) { std::cerr << "[Server] Client error: " << e.errCode << " on WinSock function: " << e.funcName << std::endl; } std::cout << "[Server] Client Disconnected!" << std::endl; } catch (const winsock_error &e) { std::cerr << "[Server] Error: " << e.errCode << " on WinSock function: " << e.funcName << std::endl; } catch (const std::exception &e) { std::cerr << "[Server] Unexpected Error! " << e.what() << std::endl; } std::cout << "[Server] Stopped!" << std::endl; } void client_thread() { std::cout << "[Client] Starting ..." << std::endl; try { // this is optional, could call connect() below in a loop instead... std::cout << "[Client] Waiting for Server ..." << std::endl; { std::unique_lock<std::mutex> lk(server_mtx); if (!server_cv.wait_for(lk, std::chrono::seconds(5), []{ return server_is_listening; })) throw std::runtime_error("Server not listening after 5 seconds!"); } // socket_ptr sConnection(::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)); if (!sConnection) WinSockError("socket"); SOCKADDR_IN addr = {}; addr.sin_family = AF_INET; addr.sin_addr.s_addr = ::inet_addr("127.0.0.1"); addr.sin_port = ::htons(server_port); if (::connect(sConnection, (SOCKADDR*)&addr, sizeof(addr)) == SOCKET_ERROR) WinSockError("connect"); std::cout << "[Client] Connected!" << std::endl; try { std::string MOTD; while (true) { MOTD = recvStr(sConnection); std::cout << "[Client] MOTD: " << MOTD << std::endl; } } catch (const connection_closed &) { } catch (const winsock_error &e) { std::cerr << "[Client] Server error: " << e.errCode << " on WinSock function: " << e.funcName << std::endl; } std::cout << "[Client] Disconnected!" << std::endl; } catch (const winsock_error &e) { std::cerr << "[Client] Error: " << e.errCode << " on WinSock function: " << e.funcName << std::endl; } catch (const std::exception &e) { std::cerr << "[Client] Unexpected Error! " << e.what() << std::endl; } std::cout << "[Client] Stopped!" << std::endl; } int main() { WSADATA wsaData; int ret = ::WSAStartup(MAKEWORD(2, 1), &wsaData); if (ret != 0) { std::cerr << "WinSock Startup failed with error: " << ret << std::endl; return -1; } std::cout << "WinSock Startup successful" << std::endl; std::thread t[num_threads]; t[0] = std::thread(server_thread); t[1] = std::thread(client_thread); for (int i = 0; i < num_threads; ++i) { t[i].join(); } ::WSACleanup(); return 0; } 的数据帧的行。我有一个purrr::pmap 下方:

reprex

reprex package(v0.2.0)于2018-07-16创建。

可以看出,我真的很想创建一个简单的输出 逐行在此给出比率library(tidyverse) # Create dummy data e <- 0.3 f <- 1:3 g <- 1:3 df <- tidyr::crossing(e = e, f = f, g = g) # Create a simple function to use new_ratio <- function(x, y, z){ return(x/(y + z)) } # Apply pmap across rows of the dataframe `df` - not working as intended purrr::pmap(df, ~ new_ratio(x = e, y = f, z = g)) #> [[1]] #> [1] 0.150 0.075 0.050 #> #> [[2]] #> [1] 0.150 0.075 0.050 #> #> [[3]] #> [1] 0.150 0.075 0.050 #> #> [[4]] #> [1] 0.150 0.075 0.050 #> #> [[5]] #> [1] 0.150 0.075 0.050 #> #> [[6]] #> [1] 0.150 0.075 0.050 #> #> [[7]] #> [1] 0.150 0.075 0.050 #> #> [[8]] #> [1] 0.150 0.075 0.050 #> #> [[9]] #> [1] 0.150 0.075 0.050 简单的例子。该函数不断返回相同的值 用于不同的输入。在第一行中,我希望 输出e/(f+g),在第二行中 0.3/(1 + 1) = 0.15

任何人都可以显示如何对此进行更正吗?我不太 从文档中了解如何应用0.3/(1 + 2) = 0.1

1 个答案:

答案 0 :(得分:1)

我们可以将列名称更改为参数名称,它应该可以工作

pmap_dbl(setNames(df, c('x', 'y', 'z')), new_ratio)
#[1] 0.150 0.100 0.075 0.100 0.075 0.060 0.075 0.060 0.050

或者,如果我们打算使用~,则参数为..,后跟数字

pmap_dbl(df, ~ new_ratio(x = ..1, y= ..2, z = ..3))
#[1] 0.150 0.100 0.075 0.100 0.075 0.060 0.075 0.060 0.050